Itgenodr017: Een interne fout is opgetreden van de soort 'DDC4AB'

Een foutmelding itgenodr017 treed op bij inlezen van Exact Online tabel [BankAccountsBulk@EOL]@bol via Invantive Bridge Online.

itgenodr017: An internal error of type ‘DDC4AB’ occurred.
Please contact your supplier. (itgenodr017, 20c82b87-185f-41c5-a86d-13b469624855).
The remote server returned an error: (500) Internal Server Error.

De call stack is:

   at Invantive.Basics.ErrorConstants.GetEnvironmentStackTrace(Boolean ignoreErrors, String valueOnError)
   at Invantive.Data.ErrorToTrace.CurrentDomain_FirstChanceException(Object sender, FirstChanceExceptionEventArgs e)
   at System.Net.HttpWebRequest.GetResponse()
   at Invantive.Data.Providers.OData.ODataProvider.DoRequest(GlobalState owner, ExecutionOptions executionOptions, HttpWebRequest request, String url, ObjectDefinition objectDefinition, String partitionCode, String callSafeNameOverrule, String anonymizedPostText, Boolean allowRetryOnConnectionLoss, ExecutionStatistics& statistics, ODataErrorProcessingInstructions& oDataErrorProcessingInstructions)
   at Invantive.Data.Providers.OData.ODataProvider.GetInternal(GlobalState owner, ExecutionOptions executionOptions, String relativeUrl, String mimeType, ObjectDefinition objectDefinition, String partitionCode, CacheSettings cacheSettings, String callSafeNameOverrule, Boolean allowRetry, Boolean preventRetryOnAuthenticationFailure, ExecutionStatistics& statistics, ODataErrorProcessingInstructions& oDataErrorProcessingInstructions)
   at Invantive.Data.Providers.OData.ODataProvider.Get[T](GlobalState owner, ExecutionOptions executionOptions, String relativeUrl, ExecutionStatistics& statistics, ObjectDefinition objectDefinition, String partitionCode, CacheSettings cacheSettings, Boolean allowRetry, Boolean preventRetryOnAuthenticationFailure, Int64& bytesRetrieved, String mimeType, String callSafeNameOverrule)
   at Invantive.Data.Providers.OData.ODataProvider.GetAndReadTextFromServiceResponse(GlobalState owner, ExecutionOptions executionOptions, List`1 rows, String basePath, List`1 allFieldTypes, String url, String partitionCode, ODataObjectDefinition objectDefinition, JsonDatabaseColumnDefinitionCollection fields, QueryObject queryObject, ParameterList parameters, Int32& pagesRetrieved, Int32& rowsRetrieved, Int64& bytesRetrieved, AdditionalResultInformation additionalInfo, String callSafeNameOverrule, Boolean allowRetry, Boolean preventRetryOnAuthenticationFailure)
   at Invantive.Data.Providers.OData.ODataProvider.BGZ.MoveNext()
   at System.Linq.Enumerable.<SelectManyIterator>d__17`2.MoveNext()
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at Invantive.Data.SqlUtility.HPB.MoveNext()
   at System.Linq.Enumerable.<SelectManyIterator>d__17`2.MoveNext()
   at Invantive.Sql.DataSourceOrFunctionTree.<GetData>d__52.MoveNext()
   at Invantive.Data.CompressedEnumerable`1.<GetEnumerator>d__8.MoveNext()
   at Invantive.Sql.FirehoseResultSet.GB.MoveNext()
   at Invantive.Sql.FirehoseResultSet.TB.MoveNext()
   at Invantive.Data.CompressedEnumerable`1.<GetEnumerator>d__8.MoveNext()
   at Invantive.Sql.FirehoseResultSet.GB.MoveNext()
   at Invantive.Sql.FirehoseResultSet.TB.MoveNext()
   at Invantive.Sql.ChainedFirehose.LB.MoveNext()
   at Invantive.Sql.FirehoseResultSet.TB.MoveNext()
   at Invantive.Sql.SelectListIterator.DE.MoveNext()
   at Invantive.Sql.FirehoseResultSet.TB.MoveNext()
   at Invantive.Data.CompressedEnumerable`1.<GetEnumerator>d__8.MoveNext()
   at Invantive.Sql.FirehoseResultSet.GB.MoveNext()
   at Invantive.Sql.MaterializeSparseArrayIterator.<Iterator>d__1.MoveNext()
   at Invantive.Data.ResultSet..ctor(GlobalState owner, ExecutionOptions executionOptions, IProviderManager manager, DatabaseColumnDefinitionCollection fields, IEnumerable`1 rows, ResultSetAuditInformation auditInformation)
   at Invantive.Sql.DdlStatementTree.<CreateTable>d__97.MoveNext()
   at Invantive.Data.CompressedEnumerable`1.<GetEnumerator>d__8.MoveNext()
   at Invantive.Sql.FirehoseResultSet.GB.MoveNext()
   at Invantive.Sql.QueryPlan.ZE.MoveNext()
   at Invantive.Data.ExtensionMethods.RTB`1.YTB.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at Invantive.Data.ConnectionManager.HD.U(QueryPlan )
   at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
   at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at Invantive.Data.ConnectionManager.ExecuteAndCombineQueryPlans(GlobalState owner, ExecutionOptions executionOptions, QueryPlan[] queryPlans, String sqlStatement, ParameterList parameters)
   at Invantive.Data.ConnectionManager.ExecuteProviderPassthroughSqlActionTable(GlobalState owner, ExecutionOptions executionOptions, String actionSql, ParameterList parameters, String callSafeNameOverrule)
   at Invantive.Data.ConnectionManager.PassthroughSqlActionTable(GlobalState owner, ExecutionOptions executionOptions, String actionSql, ParameterList parameters, String callSafeNameOverrule)
   at Invantive.Data.ActionProceduresBase.PassthroughSqlActionTable(GlobalState owner, ExecutionOptions executionOptions, String actionSql, ParameterList parameters)
   at IDH.V.ProcessStatement(GlobalState owner, ExecutionOptions executionOptions, String statement, ResultSet& resultSet, Action`2 fetchMoreRows, Action`9 executeStatement, Boolean isInInteractiveMode, ScriptingLanguageNextStepSpecification& nextStepSpecification)
   at IDH.V.ProcessStatements(GlobalState owner, ExecutionOptions executionOptions, Action`2 fetchMoreRows, Action`9 executeStatement, IEnumerable`1 statements, String sourceFileName, ScriptingLanguageNextStepSpecification& exitSpecification)
   at IDH.V.PY(String[] )
   at Invantive.Producer.QueryEngine.Program.Main(String[] arguments)

De foutcode itgenodr017 betekent dat de JSON die Invantive Bridge Online ontvangt niet geinterpreteerd kan worden omdat hij niet voldoet aan de standaard. Het kenmerk DDC4AB is een representatie van een zogenaamde AggregateException: dit is een bundeling van meerdere foutmeldingen.

Sinds zondag 11 juli 23:10:45 (UTC) treedt dit probleem op, uitsluitend op verbindingen die via de Invantive Cloud lopen. Het probleem treedt niet structureel op. De problemen met het verwerken van de JSON treden op in verschillende tabellen, verschillende velden en verschillende administraties.

Het is nog niet duidelijk waar het probleem door veroorzaakt wordt. Een uur eerder is een nieuwe release live gegaan van Invantive Cloud, waarin o.a. de nieuwe Exact Online HTTP statuscode 599 beter verwerkt wordt.

Zodra er meer informatie bekend is, zal dit topic bijgewerkt worden.

De foutmelding itgenodr017 blijft breed optreden, maar uitsluitend op Exact Online. Het gaat om verschillende tabellen, abonnementen, administraties en velden. Op sommige regels treedt een foutmelding op zoals op ExactOnlineREST.Subscription.Subscriptions:

Parse exception when converting to string: Cannot cast Newtonsoft.Json.Linq.JProperty to Newtonsoft.Json.Linq.JToken.
Can’t convert field ‘BlockEntry’ with non-parseable value to type ‘System.Nullable`1[[System.Boolean, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]’. Can not convert Object to Boolean.

De vorige versie van Invantive Bridge Online is weer geactiveerd om te kijken of er een relatie is met de wijzigingen voor HTTP 599.

Vanmiddag om 13uur weer de verversing gestart en de foutmelding op “Exactonlinerest.CRM.[Bankaccountsbulk@Eol]@bol” heeft niet opgetreden. Verversing is helemaal succesvol afgerond.

Het refreshen van SalesInvoicesBulk gaat hier nu ook goed zonder foutmeldingen. Echter er worden maar 6 regels geladen en dit zouden 10.000-en moeten zijn. Het lijkt er op dat er een toch iets nog niet goed gaat?

Zijn deze 6 verkoopfacturen gegevens uit de juiste administratie? Gegeven de interne werking is dit een hoogst ongebruikelijk probleem. Wat natuurlijk ook kan; we worden blij van bijzondere problemen.

Fijn te horen dat weer goed draait!

De oorzaak van de foutmelding itgenodr017 is inmiddels bekend.

Breaking change geen rijen / 403

Sinds december 2020 zijn door Exact een aantal breaking changes doorgevoerd zonder vooraankondiging. De software van Invantive is hierop aangepast, maar dit is helaas soms ook erg hectisch gegaan om downtime te beperken.

Een van de breaking changes was het veranderen van het gedrag van de REST API als een gebruiker geen rechten heeft in Exact Online op de gegevens. Dat kan zijn omdat de module niet gelicentieerd is (bijvoorbeeld uitlezen lijst van abonnementen in een Exact Online Salaris-omgeving) of omdat de hoofdgebruiker deze rechten niet ter beschikking heeft gesteld (toegang grootboek is een veelvoorkomende beperking).

De volgende beperking is in mei 2021 doorgevoerd:

You may have noticed that API errors were returning an empty list for users without rights or who were unauthorized. We are happy to announce that we are fixing that, and that they’ll be implemented on 1 July.
From 1 July, the correct status code will appear for authentication, rights, or license issues. Only if no records are found will you see an empty list. Here’s an overview of the fixed response codes:

  • Not authenticated – 401
  • No rights – 403
  • Feature not available in license – 403
  • No records found – empty list
    This change also conforms to the HTTP standard status code, both conforming to standards and tightening security.

Een verdere toelichting is te vinden op Itgeneor228 / itgenoda060: Forbidden - User division is not within division scope.

Bestaande programmatuur op de REST API’s ging er van uit dat oorspronkelijke gedrag van 0 rijen teruggeven behouden blijft. Nog sterker, de XML API’s gaven en geven wel een 403 foutmelding. Dit is instelbaar via ignore-http-403-errors, die tegenwoordig standaard op true staat voor de REST API’s, zodat de 403 foutmeldingen onderdrukt worden. Vooral onervaren Power BI gebruikers hadden veel moeite met begrijpen van de foutmeldingen in de XML API-gebaseerde tabellen.

De formele route om dit 403-probleem op te lossen was om vooraf telkens om per administratie en per tabel op XML en REST te vragen aan de Exact Online API of de gebruiker rechten heeft via een API. Deze API bleek nog niet opgewassen tegen serieus productiegebruik. In mei is toen de keuze gemaakt om de 403-foutmeldingen te laten voor wat ze zijn. Niet deftig, maar het realistisch best haalbare zonder gebruikers te frustreren.

Test, test, test en de itgenodr017 foutmelding

Het inschakelen van de per 1 juli aangekondigde wijzigingen verloopt volgens een niet-bekende planning. Het limiteren van het aantal errors (zoals 403) zou 5 juli wereldwijd geactiveerd zijn en 12 juli verbeterd. In het kader van een analyse is onderzocht hoe de limieten overschreden kunnen worden zodat de Invantive SQL-engine een zo optimaal mogelijk gedrag kan vertonen.

Het overschrijden bleek niet te lukken; mogelijkerwijs zijn de limieten niet doorgevoerd of werken ze anders dan gepland.

Echter, doordat de SQL-engine aangepast was om dergelijk relatief low-level fouten af te vangen en door te geven is door Invantive een bug geintroduceerd in het cachemechanisme. Deze bug treedt alleen op voor gegevens op specifieke administraties en tabellen waar de gebruiker geen rechten op heeft. Feitelijk wordt een Exact Online HTTP 403-foutmelding gecached inclusief de daarbijhorende JSON. Het omzetten bij een tweede aanroep van dezelfde administratie en tabel door een gebruiker zonder rechten zal proberen de JSON als een HTTP 200-melding (“OK”) te behandelen en leidt tot de geschetste foutcode itgenodr017.

De analyse was bewerkelijk omdat relevante achtergrondinformatie verdween gedurende de foutafhandeling. Dit is inmiddels verbeterd zodat een analyse sneller tot resultaten leidt.

De storing duurde relatief lang omdat de testcases een Exact Online test-omgeving gebruiken waar de gebruiker relatief veel rechten heeft, zodat alle API’s getest kunnen worden op correct gedrag. De API-testcases focussen beduidend minder op incorrect gedrag.

In de volgende release zal nogmaals geprobeerd worden deze wijziging te verwerken, maar dan zonder de gevolgschade.

Het zijn 6 verkoopfacturen uit 1 van de 4 administraties. Ik begrijp het ook niet.

Ik heb geprobeerd om eens via de SQL Editor van Invantive deze tabel te bevragen om te kijken of ik dan ook maar 6 regels krijg:

select top 10  *
from   ExactOnlineREST.SalesInvoice.SalesInvoicesBulk
limit  1000

maar dan krijg ik dus deze melding:
Invantive Cloud SQL editor error itgenodr017

E.e.a. is geanalyseerd. De engine verwerkt in dit geval de verkoopfacturen van 4 administraties.

De keuze van de administraties kan gestuurd worden op SQL niveau via het use statement, in de Invantive Cloud SQL editor via de keuzelijst rechtsboven, via de database “On Startup” of via Power BI of via Exact Online.

Het verwerken van de gegevens uit verschillende administraties gebeurt gelijktijdig. Niet met honderden tegelijk, want dat zou een oneerlijke belasting zijn van Exact Online, maar wel tot het aantal ingesteld via de driverattribuut requests-parallel-max. Die is meestal 8.

In dit geval zullen alle vier de administraties gelijktijdig uitgelezen worden. De data komt streaming binnen vanuit het platform (in dit geval Exact Online, maar dit streaming concept geldt voor vrijwel alle platformen). De data landt in buffers tussen Exact Online en Bridge Online. De omvang van de buffers wordt automatisch aangepast op basis van de leessnelheid bij Exact Online en de uitgifte snelheid van Bridge Online. De maximale snelheid bij Exact Online ligt voor de meeste gevallen rond 2 MB compressed, 20 MB uncompressed (met een brede spreiding) per seconde, maar aanmerkelijk hoger voor documentbijlagen. Normaliter heeft Bridge Online een doorvoersnelheid van 500 MB compressed, 5 GB uncompressed per seconde, maar niet iedere Power BI client zal zo snel kunnen inlezen.

Merk op dat zowel richting Exact Online als vanuit Bridge Online gebruik gemaakt wordt van caches. Dit is ook zichtbaar in de systeemplaat.

Streaming zorgt er voor dat de data al terugkomt terwijl niet alles opgehaald is, maar komt ook met nadelen zoals bijvoorbeeld het probleem omschreven op Itgenclr078: Newtonsoft.Json.JsonReaderException / zorgen stabiliteit Exact Online.

Naarmate de vier streamingstromen zich vullen met rijen, worden de vier stromen gemengd tot 1 uitvoer. Omdat de antwoorden vanuit Exact Online soms bij de ene administraties soms een milliseconde sneller terugkomen dan bij de ander, worden de gegevens gemengd teruggegeven. Het is dus niet zo dat eerst alle gegevens van administratie 1 terugkomen, daarna administratie 2, etc. Het is rustig mogelijk dat de ene dag eerst 3 regels uit administratie 1 terugkomen, daarna 100 uit 2, etc.

In dit geval blijkt uit de analyse dat de gebruiker op drie van de divisies: 15…04 (’.’ betekent cijfer verborgen), 25…31 en 27…14 geen rechten heeft op de verkoopfacturen. Er komt terug bijvoorbeeld:

Content length: 82
Is from cache: False
Protocol version: 1.1
Response URI: https://start.exactonline.nl/api/v1/15...04/bulk/SalesInvoice/SalesInvoices?$select=SelectionCode,SelectionCodeCode,SelectionCodeDescription,AmountDC,AmountDiscount,AmountDiscountExclVat,AmountFC,...,YourRef,SalesChannel,SalesChannelCode,SalesChannelDescription
Header Cache-Control: no-store, no-cache
Header Connection: keep-alive
Header Content-Length: 82
Header Content-Type: application/json
Header DataServiceVersion: 1.0;
Header Date: Wed, 14 Jul 2021 09:01:02 GMT
Header Expires: -1
Header Pragma: no-cache
Header Referrer-Policy: strict-origin-when-cross-origin
Header Set-Cookie: ASP.NET_SessionId=...; SameSite=lax; path=/; secure; HttpOnly; SameSite=Lax, ExactServer{...}=Division=15...04; SameSite=lax; path=/; secure; HttpOnly, ExactOnlineClient=...=; SameSite=lax; expires=Mon, 31-Dec-2198 23:00:00 GMT; path=/; secure; HttpOnly
Header Strict-Transport-Security: max-age=31536000 ; includeSubDomains ; preload
Header X-Content-Type-Options: nosniff
Header X-RateLimit-Limit: 50000
Header X-RateLimit-Minutely-Limit: 300
Header X-RateLimit-Minutely-Remaining: 299
Header X-RateLimit-Minutely-Reset: 1626253320000
Header X-RateLimit-Remaining: 49972
Header X-RateLimit-Reset: 1626307200000
Header X-XSS-Protection: 1; mode=block

{
"error": {
"code": "", "message": {
"lang": "", "value": "Forbidden"
}
}
}

Afhankelijk van de reactiesnelheid wordt door de bug deze foutmelding verkeerd verwerkt. Op Invantive Bridge Online is de versie teruggezet naar een voorgaande. Op Invantive Cloud staat nog de huidige versie, die dus een itgenodr017 zal geven. Een oplossing hiervoor staat klaar als volgende release. Die zal uitsluitend op Cloud gezet worden in afwachting van een mogelijke livegang morgen door Exact Online van een deel van de geplande wijzigingen.

De nieuwe release van Invantive Cloud is live gegaan, waarin ook queries op tabellen weer naar behoren werken ook als de gebruiker op een deel van de tabellen geen rechten heeft.