Troubleshooting
Common issues when managing DIDs in ISBE and their solutions.
Errors during DID Onboarding
400 Bad Request when calling insertFirstDidDocument
Possible causes:
proofdoes not matchdid+publicKey— Regenerate the DID/PublicKey/Proof triplet with./did-gen did -p ...to ensure consistency.vMethodIdwith incorrect format — Must be 32 bytes in base64url without padding (exact 43 characters). The JWK thumbprint meets this format by default.publicKeywith wrong prefix — Forsecp256k1, it must start with0x04(uncompressed format).modelDeployof the DID does not match the network — If you call the PRO API with adid:isbe:uc-pre:...DID, the operation fails. Ensure match among all three values: network, DID, and API.
The transaction is sent but the DID does not appear
- Review the
statusfield of thereceipt. If it is0, the transaction was executed but the smart contract reverted. Typical causes:- The
fromEOA does not have authorization to callinsertFirstDidDocument(that operation has special authorization). - The DID already exists.
- The
- If
statusis1but the GET still returns404, wait a few seconds for the indexer to reflect the new block.
Signing Errors
cli-tx-save throws a JSON error when passing the body
If you are using the internal cli-tx-save binary, the -t parameter expects a JSON string inside single quotes. If the JSON contains internal double quotes and you pass it in double quotes, it breaks. Solution:
./sign-tx sign -p 0x<KEY> -t '{"to":"0x...","data":"0x..."}'
If it still gives you trouble, the most portable alternative is to sign with ethers.js or eth_account directly (see Registration via API — step 4).
ethers.js throws "from must be undefined or match the signer"
The POST /contract/... endpoints return from inside the object. ethers refuses to serialize a transaction with a from different from the signer. Solution: discard it before building the Transaction:
const tx = Transaction.from({ ...raw, from: undefined });
eth_account complains about hexadecimal fields
Unlike ethers, eth_account expects native integers in gas, gasPrice, nonce, value, and chainId. Convert the hex 0x... with int(x, 16) before signing.
The signed transaction is rejected with nonce too low
The nonce returned by the API is the EOA's current nonce. If you sent another transaction between generating and signing this transaction, the nonce may have become obsolete. Solution: call the endpoint again to regenerate the transaction.
Errors when Adding Verification Methods
The key does not appear as assertionMethod
Remember that the API exposes the steps separately:
addVerificationMethodregisters the key.addVerificationRelationshipassociates it with the use (assertionMethod,authentication, etc.).
If you only execute the first one, the key exists but is not usable for signing credentials.
publicKeyType and publicKey format misaligned
publicKeyType determines the format of the publicKey field, not the curve. The curve comes from the registered material itself:
publicKeyType: "secp256k1"→publicKeymust be 64 XY hexadecimal bytes (uncompressed format without JWK wrapper). If you paste a serialized JWK here, the API responds with400due to invalid format.publicKeyType: "JsonWebKey2020"→publicKeymust be a valid JWK serialized to a JSON string and encoded in hex. The actual curve is read from thecrvfield inside the JWK. It acceptssecp256k1,P-256, etc.
Common errors:
publicKeyType: "secp256k1"with a serialized JWK inpublicKey→400 BAD_REQUEST. Input the JWK withpublicKeyType: "JsonWebKey2020", or extract the 64 XY bytes of the secp256k1 key and send them as pure hex.publicKeyType: "P-256"literal →400 UNSUPPORTEDwith the message "The 'P-256' publicKeyType is temporarily unsupported." The value is reserved in the spec but disabled in the current implementation; useJsonWebKey2020withcrv: "P-256"instead.publicKeyType: "JsonWebKey2020"with a JWK whosecrvis not supported by the contract → the insertion may pass format validation, but the key will not be operational for signing. The curves proven to be functional aresecp256k1andP-256.
Confusion with the from EOA
from must always be the EOA of the control secp256k1 key of the DID, not the EOA derived from the new P-256 key. The P-256 is used for off-chain signing; on-chain transactions are signed by the secp256k1.
Resolution Errors
404 Not Found
- The DID is not registered in that environment (check the
modelDeploy). - The DID is incorrectly URL-encoded. Some HTTP clients require encoding the
:of the DID. Try with cURL first to discard.
406 Not Acceptable
The Accept header is not one of the supported ones:
application/did+ld+jsonapplication/did+json
Funds / Gas Errors
insufficient funds for gas
The EOA has no balance. In PRE, you can request funds in the Faucet section of the portal. In PRO, funds are assigned in the initial onboarding; contact ISBE if you need more.
gas required exceeds allowance
The gasLimit returned by the API should be sufficient. If you encounter this error, do not modify the gasLimit manually: regenerate the transaction so that the API recalculates it.
Trust Chain Errors
The CLI says that the accreditation is invalid
Common causes:
accreditedForandaccreditedSchemasdo not have the same cardinality. There must be a 1:1 correlation.- The types / schemas are not a subset of those accredited by the parent accreditation.
- The
domaindoes not match that of the parent accreditation. - The URL in
accreditedByis not accessible or returns an invalid JWT.
The verifier cannot find my accreditation
- Confirm with ISBE that the accreditation has been published in the TIR.
- Verify that the verifier points to the TIR of the correct environment.
Asking for Help
If you still have problems after reviewing these points, open an issue in the ISBE support portal attaching:
- Environment (
PRE/PRO). - Affected DID.
- Endpoint and request body.
- Complete response (including
tx_hashif the transaction was sent). - CLI logs if the issue is local.