Codici di errore della DI API di SAP B1: che cosa significano -5002, -1029, -2035 e -5006 e come risolverli

By Zain Abbas, Kodenova · Updated

Short answerUna chiamata alla DI API restituisce 0 in caso di successo e un codice negativo in caso di errore. Legga codice e testo con Company.GetLastError subito dopo la chiamata fallita. I codici più frequenti nei progetti reali sono -5002 (un contenitore di validazioni; il testo che segue indica il campo reale), -1029 (il campo non può essere aggiornato), -2035 (il record esiste già), -2028 (nessun record corrispondente), -5006 (azione non supportata, ad esempio Cancel su una fattura cliente) e -5001 (errore interno, spesso un null nel payload del Service Layer).

Una chiamata alla DI API restituisce 0 in caso di successo e un numero negativo in caso di errore. Il numero indica la categoria; il testo di Company.GetLastError indica la causa. Nelle integrazioni SAP Business One che sviluppo (portali web, add-on, bridge di fatturazione elettronica), sette codici coprono quasi tutti gli errori: -5002, -1029, -2035, -2028, -5006, -5001 e -4006. Qui sotto trova che cosa significa ciascuno, il messaggio esatto restituito da SAP nei nostri test e la soluzione.

Come si legge correttamente un errore della DI API?

Ogni Add(), Update(), Cancel() e Remove() restituisce un int. Se non è 0, chiami GetLastError subito. L’errore appartiene all’oggetto Company e la chiamata DI successiva lo sovrascrive, quindi una riga di log scritta dopo una seconda chiamata mostra spesso l’errore sbagliato o nessun errore.

Due trappole da progetti reali:

  1. Codice .NET con late binding. Se usa dynamic per l’oggetto Company, c.GetLastError(out int code, out string msg) genera Could not convert argument 0 for call to GetLastError. Il binder dinamico di .NET non riesce a passare argomenti COM out. Lo chiami invece tramite reflection.
  2. Registrare solo il numero. -5002 da solo non serve a nulla. Il testo contiene un numero di messaggio interno e spesso il campo esatto, come [INC1.UomCode] o [DocumentLines.UnitPrice][line: 1].
// Read the DI error without dynamic: works with late binding (no Interop DLL)
public static (int Code, string Message) ReadLastError(object company)
{
    var args = new object[] { 0, null };
    var byRef = new ParameterModifier(2);
    byRef[0] = true; byRef[1] = true;
    company.GetType().InvokeMember("GetLastError",
        BindingFlags.InvokeMethod, null, company, args,
        new[] { byRef }, CultureInfo.InvariantCulture, null);
    return (Convert.ToInt32(args[0]), Convert.ToString(args[1]) ?? "");
}

int rc = doc.Add();
if (rc != 0)
{
    var (code, msg) = ReadLastError(company);   // read it NOW, before any other DI call
    log.Error("DI Add failed [{Code}] {Msg}", code, msg);
}

Nel Service Layer gli stessi codici tornano in JSON, ad esempio {"error":{"code":-4006,"message":{"lang":"en-us","value":"Update the exchange rate"}}}.

Quali codici di errore della DI API compaiono più spesso?

CodiceTesto SAP (breve)Che cosa significa di solitoPrima cosa da verificare
-5002Variabile, ad es. “UoM code cannot be empty [INC1.UomCode]”Una validazione di business è fallita; il testo indica il campoLegga il campo tra parentesi quadre
-1029“Field cannot be updated”Ha modificato un campo che SAP blocca su quel documento o recordStato del documento, righe registrate, registrazioni contabili
-2035“This entry already exists in the following tables”Chiave duplicata: UDF, UDT, codice BP, codice articoloVerifichi l’esistenza prima di Add
-2028“No matching records found”La chiave, il codice o la query salvata non esiste in questa societàDatabase aziendale e chiave esatta
-5006“The requested action is not supported for this object”Metodo sbagliato per quel tipo di oggetto, ad es. Cancel su una fatturaUsi il metodo supportato da quell’oggetto
-5001“Internal error”Input malformato, spesso un valore null nel corpo di una chiamata al Service LayerRimuova i null e le stringhe vuote
-4006“Update the exchange rate”Nessun cambio per la valuta del documento in quella dataORTT per la data di registrazione

Che cosa significa -5002 in SAP Business One?

-5002 è un contenitore. SAP lo restituisce per la maggior parte delle validazioni su documenti e dati anagrafici e mette la vera causa nel testo. Questi sono messaggi ottenuti su società di test reali, con la soluzione per ciascuno:

  • [-5002] 1470000542 - UoM code cannot be empty [INC1.UomCode] su una conta d’inventario. L’articolo aveva un gruppo di unità di misura con due unità (MT/KG); gli articoli con una sola unità passavano. Soluzione: inviare UoMCode (l’unità di misura di magazzino dell’articolo) con la quantità contata.
  • [-5002] 480000112 ... does not exist su un’uscita merci con numeri di serie. Avevamo inviato il numero di serie interno. I documenti in uscita richiedono il SystemSerialNumber (il numeratore che SAP assegna per articolo). Usi il numero di serie interno e quello del produttore solo per i ricevimenti.
  • “G/L Increase account is missing” su una rivalutazione di magazzino. La società non aveva conti di aumento/diminuzione impostati per il periodo o per alcun magazzino. È un problema di configurazione, non di codice: imposti i conti nella determinazione dei conti Co.Ge.
  • Documento base già chiuso. Copiare una consegna da un ordine cliente già consegnato del tutto o chiuso fallisce con -5002. Verifichi la riga base prima di costruire il documento di destinazione (query più sotto).
  • Un UDF di tipo Float senza SubType. Creare un UDF numerico con st_None o senza EditSize ha restituito -5002. Imposti SubType su Price, Quantity, Rate, Sum o Percentage e definisca la dimensione.
  • Un trasferimento basato su una richiesta di trasferimento. Alcune build della DI API hanno rifiutato una riga OWTR collegata a una base OWTQ (BaseType 1250000001) che il Service Layer accettava con gli stessi dati. Ora riproviamo una volta come copia semplice e chiediamo all’utente di chiudere la richiesta a mano.
  • Allegati su un oggetto chiuso. SAP ha accettato collegamenti ad allegati solo su accordi quadro in bozza e chiamate di assistenza aperte. Accordi approvati e chiamate chiuse hanno risposto -5002.

Un altro caso che ci è costato un pomeriggio: quando abbiamo provato a creare tramite il Service Layer un UDF già esistente, SAP non ha restituito -2035 ma [-5002] No records. Non si affidi quindi solo a -2035 per riconoscere un “esiste già”; controlli prima CUFD.

Perché compare -1029 “Field cannot be updated”?

-1029 significa che il campo esiste ma SAP non permette di modificarlo nello stato attuale dell’oggetto. Il campo tra parentesi quadre indica quale. Casi dai nostri test:

  • [-1029] [DocumentLines.UnitPrice][line: 1] 'Field cannot be updated' su un reso cliente e su una nota di credito cliente. Una volta registrate, SAP blocca prezzo e sconto su quelle righe. Le note di testata si possono ancora aggiornare.
  • [ORDR.VatSum] modificando un documento di vendita chiuso. I documenti chiusi e annullati accettano modifiche ai commenti, ma qualsiasi modifica a righe, prezzi o imposte dà -1029. Verifichi DocStatus prima di mostrare un pulsante di modifica.
  • [OACT.Postable] “disattivando” un conto Co.Ge. che ha già registrazioni. Il portale modificava la proprietà sbagliata. Per rendere inattivo un conto, imposti FrozenFor = Y (con FrozenFrom / FrozenTo se serve un intervallo di date) e lasci stare Postable.
  • Una riga di ordine d’acquisto copiata. Quando una riga di OA è stata ricevuta in parte (quantità aperta inferiore alla quantità), SAP ne blocca prezzo, sconto e quantità. Blocchi quei campi nella sua interfaccia, così l’utente non incontra mai l’errore.

Una vecchia discussione su SAP Community mostra lo stesso codice su ORDR.DocRate, quindi non è un comportamento nuovo. Interpreti -1029 come “la sua interfaccia ha lasciato modificare all’utente qualcosa che SAP considera definitivo”.

Come si risolve -2035 “This entry already exists”?

-2035 è una chiave duplicata. Compare soprattutto quando un add-on o un’integrazione crea le proprie UDT e UDF all’avvio, o quando un’importazione invia due volte lo stesso codice BP o articolo.

Renda idempotente la creazione dello schema: cerchi prima il campo, lo crei solo se manca e consideri -2035 in creazione come un successo. Per i dati di business, verifichi tramite la sua chiave esterna prima di Add(). Per fatture clienti o fornitori da un’importazione, la chiave è CardCode più NumAtCard.

-- SQL Server: does the UDF exist? (TableID without @ for system tables)
SELECT FieldID, AliasID, Descr
FROM   CUFD
WHERE  TableID = 'OITM' AND AliasID = 'HSCode';

-- SAP HANA
SELECT "FieldID", "AliasID", "Descr"
FROM   "CUFD"
WHERE  "TableID" = 'OITM' AND "AliasID" = 'HSCode';

-- Is the base sales order line still open before you copy it? (SQL Server)
SELECT T0.DocNum, T0.DocStatus, T1.LineNum, T1.LineStatus, T1.OpenQty
FROM   ORDR T0 JOIN RDR1 T1 ON T1.DocEntry = T0.DocEntry
WHERE  T0.DocEntry = 1234;

-- SAP HANA
SELECT T0."DocNum", T0."DocStatus", T1."LineNum", T1."LineStatus", T1."OpenQty"
FROM   "ORDR" T0 JOIN "RDR1" T1 ON T1."DocEntry" = T0."DocEntry"
WHERE  T0."DocEntry" = 1234;

Tenga presente che AliasID in CUFD è memorizzato senza il prefisso U_.

Che cosa significa -2028 “No matching records found”?

Il record richiesto non si trova in questo database aziendale. Nella DI API, GetByKey restituisce false invece di sollevare -2028, quindi ne verifichi sempre il risultato. Nel Service Layer si ottiene -2028 su un GET per chiave e anche su SQLQueries('code')/List quando la query salvata non esiste in quella società. Questo caso, e come ricreare la query in automatico, è trattato nella guida agli errori di SQLQueries del Service Layer.

Cause frequenti: è collegato a un’altra società (test invece di produzione), il codice ha maiuscole diverse o spazi finali, oppure la chiave è un DocNum dove SAP si aspetta un DocEntry.

Perché Cancel() restituisce -5006 su una fattura cliente?

-5006 indica che il metodo non è supportato per quell’oggetto. Il caso classico: Documents.Cancel() su una fattura cliente o su una consegna. SAP annulla i documenti contabili creando un documento di storno. Carichi la fattura, chiami CreateCancellationDocument(), che restituisce un nuovo documento in memoria (non un int), poi chiami Add() su di esso. L’originale risulta quindi annullato.

Ordini cliente, ordini d’acquisto, richieste d’acquisto e offerte supportano il semplice Cancel(). Le registrazioni di magazzino funzionano al contrario: nella versione della DI API che usiamo, entrate merci (59), uscite merci (60) e trasferimenti di magazzino (67) non espongono affatto CreateCancellationDocument, mentre Cancel() funziona. Associ il metodo a ciascun tipo di oggetto invece di usare un unico percorso di annullamento per tutto.

Che cosa causa -5001 “Internal error”?

Un semplice -5001 Internal error non indica nulla, e questo lo rende il più difficile da rintracciare. Nel nostro lavoro con il Service Layer la causa era un corpo JSON con "Field": null. In .NET, JsonIgnoreCondition.WhenWritingNull salta le proprietà null degli oggetti ma non i valori null di un dizionario, quindi un payload costruito da un Dictionary<string, object> li invia comunque. Soluzione: aggiunga i campi tramite una funzione di supporto che scarta null e stringhe vuote, e da quella fonte non vedrà più -5001.

Come si risolve -4006 “Update the exchange rate”?

Il documento è in valuta estera e in ORTT non c’è un cambio per quella valuta alla data di registrazione. SAP non indovina un cambio. Carichi prima il cambio del giorno, oppure imposti DocRate sul documento quando il sistema di origine ha già il cambio concordato.

-- SQL Server: is there a rate for USD on the posting date?
SELECT RateDate, Currency, Rate FROM ORTT
WHERE  Currency = 'USD' AND RateDate = '2026-10-25';

-- SAP HANA
SELECT "RateDate", "Currency", "Rate" FROM "ORTT"
WHERE  "Currency" = 'USD' AND "RateDate" = '2026-10-25';

Che cosa significano gli errori di connessione -111, -132 e -8037 della DI API?

Questi tre arrivano da Company.Connect(), prima che venga toccato qualsiasi documento. -111 significa che la DI API non è riuscita ad aprire il database SBO-COMMON, -132 che il login a SAP Business One è stato rifiutato, e -8037 che la DI API non ha raggiunto il System Landscape Directory (SLD) con il nome di server indicato.

CodiceTesto SAPCausa abitualePrima verifica
-111“Failed to connect to SBO-Common”La DI API non riesce ad accedere a SBO-COMMON: Server o DbServerType errati, credenziali del database errate o una patch della DI API diversa da quella del serverNome del server e DbServerType; installi la DI API dalla stessa patch del server
-132“Error during SBO user authentication”LicenseServer non impostato, una patch della DI API diversa da quella della società o impostazioni di login misteImposti LicenseServer; con UseTrusted = true lasci vuoti DbUserName e DbPassword; Server e SLDServer devono coincidere, maiuscole e minuscole comprese
-8037“Failed to connect or logon to SLD”Company.Server non è il nome registrato nell’SLD / Control Center (ad esempio localhost), oppure b1-local-machine.xml nella cartella Conf della DI API punta a un altro serverUsi il nome esatto del server registrato; copi b1-local-machine.xml dalla cartella Conf del client SAP Business One alla cartella Conf della DI API

Due note su -132. SAP lo collega al fatto che la connessione della DI API alla società non è autenticata sul license server (SAP KBA 3394748). E può comparire solo di tanto in tanto: la SAP KBA 3663692 descrive un -132 intermittente quando molti login DI API o Service Layer avvengono contemporaneamente, quindi un portale web che apre una nuova connessione a ogni richiesta dovrebbe invece riutilizzarne una.

Come dovrebbe gestire questi errori un’integrazione?

Ciò che funziona per noi in produzione:

  1. Registrare codice, testo completo, tipo di oggetto e il proprio riferimento (ad esempio il numero d’ordine del portale) a ogni errore.
  2. Dividere gli errori tra “riprova” e “fermati”. Un timeout o una sessione persa si possono ritentare. -5002, -1029, -2035 e -5006 sono problemi di dati o di progettazione: ritentarli crea solo rumore. Per una query salvata mancante (-2028 su SQLQueries), ricrearla e riprovare una volta è sicuro.
  3. Tradurre per l’utente, conservare il testo originale per l’assistenza. “Questa riga è già stata ricevuta, quindi il prezzo è bloccato” aiuta un buyer più di [-1029] [DocumentLines.UnitPrice]. Aggiunga il testo di SAP in una sezione di dettaglio.
  4. Prevenire invece di intercettare. La maggior parte dei casi -1029 e -5002 descritti sopra è sparita quando l’interfaccia ha iniziato a controllare lo stato del documento, lo stato della riga o la configurazione dell’articolo prima dell’invio.

Se sta scegliendo tra le due API per un nuovo progetto, la guida allo sviluppo di add-on e la guida al Service Layer le confrontano. Il riferimento tabelle elenca le tabelle usate nelle query qui sopra, e il creatore di richieste Service Layer la aiuta a testare un payload prima che arrivi al suo codice. Se le serve un’integrazione o un add-on sviluppato e mantenuto, veda Sviluppo SAP Business One.

I messaggi di errore citati provengono da test di Kodenova su società di test SAP Business One 10.0 (DI API e Service Layer), ottobre 2026.

Sources

Related services

FAQ

Frequently asked questions

Dove si trova l'elenco completo dei codici di errore della DI API di SAP Business One?

SAP non pubblica un elenco completo e aggiornato. La guida dell'SDK spiega GetLastError, e la parte utile è il testo del messaggio che accompagna il codice. Un -5002 in particolare copre centinaia di validazioni diverse, quindi registri nel log il testo completo, non solo il numero.

Il Service Layer e la DI API restituiscono gli stessi codici di errore?

Per lo più sì. Il Service Layer si basa sulla stessa logica di business, quindi -5002, -1029, -2035 e -2028 hanno lo stesso significato in entrambi. Il Service Layer li racchiude in JSON: error.code ed error.message.value.

Come si annulla una fattura cliente tramite la DI API?

Non con Cancel(), che restituisce -5006. Chiami CreateCancellationDocument() sulla fattura caricata, poi esegua Add() sul documento restituito. Ordini cliente, ordini d'acquisto e offerte supportano invece Cancel().

Perché Company.Connect() restituisce -132?

-132 "Error during SBO user authentication" significa che la DI API ha raggiunto il server ma il login a SAP Business One è fallito. Verifichi che LicenseServer sia impostato, che la patch della DI API corrisponda alla versione del database aziendale, che usi una sola modalità di login (con UseTrusted = true lasci vuoti DbUserName e DbPassword) e che Server e SLDServer usino lo stesso nome con le stesse maiuscole e minuscole. SAP documenta anche un -132 intermittente quando molti login DI API o Service Layer avvengono contemporaneamente.

Iniziamo?

Ci descriva di cosa ha bisogno. Riceverà una risposta tecnica chiara, un perimetro definito e un prezzo, di norma entro 24 ore.