SDK Troubleshooting
This guide covers common issues when working with the OpenTDF SDKs and how to resolve them.
This section covers issues when using the SDKs in your applications. For platform installation and setup issues, see docs.opentdf.io — Managing the Platform or your platform's deployment documentation.
Authentication Failed
Error: rpc error: code = Unauthenticated or 401 Unauthorized
Solution: Verify your credentials are correct:
otdfctl auth client-credentials <client-id> <client-secret>
Check that your identity provider is accessible:
curl https://<idp-endpoint>/
Token Expired
Error: token expired, invalid token, or jwt expired
Cause: The authentication token's lifetime has been exceeded. OIDC tokens are short-lived by default.
Solution:
-
Re-authenticate (CLI):
otdfctl auth client-credentials <client-id> <client-secret> -
Implement token refresh in your application: The JavaScript SDK's
refreshAuthProviderhandles automatic token renewal:import { AuthProviders } from '@opentdf/client';
const authProvider = AuthProviders.refreshAuthProvider({
clientId: 'your-client-id',
exchange: 'client_credentials',
clientSecret: 'your-client-secret',
oidcOrigin: 'https://<idp-endpoint>', // Keycloak: append /realms/<realm>; adjust path for your IdP
}); -
Re-instantiate the SDK: For Go and Java, create a new SDK instance with fresh credentials when a token error occurs.
Certificate Errors (SSL/TLS)
Error: x509: certificate signed by unknown authority or Failed to validate TLS certificates
Cause: The platform is using a self-signed or privately-issued certificate that your system doesn't trust.
Solution:
-
Trust the platform's CA certificate on your system:
# macOS
sudo security add-trusted-cert -d -r trustRoot \
-k /Library/Keychains/System.keychain ca-cert.pem
# Linux
sudo cp ca-cert.pem /usr/local/share/ca-certificates/platform-ca.crt
sudo update-ca-certificates# Windows (PowerShell as Administrator)
Import-Certificate -FilePath ca-cert.pem -CertStoreLocation Cert:\LocalMachine\RootObtain the CA certificate from your platform administrator or deployment documentation.
-
Restart your browser and terminal after trusting the certificate — applications must reload their certificate stores to pick up the change.
-
Skip certificate verification (quick workaround for CLI only, not recommended for production):
export OTDFCTL_TLS_NO_VERIFY=true
Connection Refused
Error: connection refused or platform unreachable
Solution: Verify your platform is running:
curl https://<platform-endpoint>/healthz
Should return: {"status":"SERVING"}
If not running, restart your platform services according to your deployment documentation.
Import Errors
Go: package github.com/opentdf/platform/sdk is not in GOROOT
go mod tidy
go get github.com/opentdf/platform/sdk@latest
Java: package io.opentdf.platform.sdk does not exist
mvn clean install -U
JavaScript: Cannot find module '@opentdf/client'
npm install @opentdf/client
Permission Denied / Insufficient Entitlements
Error: When attempting to decrypt a TDF, you may see different error formats depending on your SDK:
- Go
- Java
- JavaScript
reader.WriteTo failed: splitKey.unable to reconstruct split key: map[{https://<kas-endpoint> }:tdf: rewrap request 403
kao unwrap failed for split {https://<kas-endpoint> }: permission_denied: request error
rpc error: code = PermissionDenied desc = forbidden]
What to Look For: The meaningful information is buried in the error. Look for:
PermissionDeniedorforbiddenrewrap request 403permission_denied: request error
io.opentdf.platform.sdk.SDK$SplitKeyException: splitKey.unable to reconstruct split key:
{KeySplitStep{kas='https://<kas-endpoint>/kas', splitID=''}=io.opentdf.platform.sdk.SDKException: error unwrapping key}
error unwrapping key
What to Look For: The meaningful information is:
splitKey.unable to reconstruct split keyerror unwrapping keySplitKeyException
Error: splitKey.unable to reconstruct split key
error unwrapping key
What to Look For: The meaningful information is:
unable to reconstruct split keyerror unwrapping key
These errors indicate an authorization failure, not a cryptographic or network issue. You may also see key access denied from the KAS directly.
Cause: Your identity lacks the required entitlements (attribute values) to decrypt the TDF. This is ABAC (Attribute-Based Access Control) working correctly.
For example, if you encrypted data with https://example.com/attr/department/value/marketing, you need a subject mapping that grants you the marketing entitlement.
Solution: Grant yourself (or the entity) entitlements by creating a subject mapping.
Quick fix using the CLI:
# Get the ID of the attribute value you want to grant
export ATTRIBUTE_VALUE_ID=$(otdfctl policy attributes list --json | \
jq -r '[.attributes[] | select(.name=="department") | .values[] | select(.value=="marketing")][0].id')
# Create a subject condition set (if needed)
otdfctl policy subject-condition-sets create \
--subject-set '[".clientId == \"<your-client-id>\""]' \
--label "My Service Account"
export SUBJECT_CONDITION_SET_ID=<id-from-output>
# Create the subject mapping to grant the entitlement
otdfctl policy subject-mappings create \
--action read \
--attribute-value-id $ATTRIBUTE_VALUE_ID \
--subject-condition-set-id $SUBJECT_CONDITION_SET_ID
TDF Format Error
Error: invalid TDF format, malformed TDF, or tamper detected
Cause: The file was corrupted during transfer, modified after encryption, or was created with an incompatible TDF version.
Solution:
- Re-encrypt the original file — if you have access to the plaintext, create a fresh TDF
- Check SDK version compatibility — the SDK used to decrypt must support the TDF format version used to encrypt (e.g., TDF3 vs nanoTDF)
- Verify file integrity — TDFs are tamper-evident; any modification after encryption will cause decryption to fail
- Check file transfer — binary TDF files can be corrupted by text-mode transfers; ensure files are transferred in binary mode
Entity Resolution Failed
Error: entity resolution failed or failed to resolve entity
Cause: The platform cannot map your identity (from the OIDC token) to an entity with attributes. This happens when subject mappings are not configured for your identity provider claims.
Solution: Create a subject mapping that connects your IdP identity to the appropriate attribute entitlements:
# Create a subject condition set matching your identity
# (replace the selector with the claim from your OIDC token, e.g. clientId, email, group)
otdfctl policy subject-condition-sets create \
--subject-set '[".clientId == \"<your-client-id>\""]' \
--label "Your App Service Account"
export SCS_ID=<id-from-output>
# Get the ID of the attribute value to grant
export ATTRIBUTE_VALUE_ID=$(otdfctl policy attributes list --json | \
jq -r '[.attributes[] | select(.name=="department") | .values[] | select(.value=="engineering")][0].id')
# Map the condition set to the attribute value
otdfctl policy subject-mappings create \
--action read \
--attribute-value-id $ATTRIBUTE_VALUE_ID \
--subject-condition-set-id $SCS_ID
For more detail on configuring subject mappings, see Policy Management.
Resource Already Exists
Error: already_exists: resource unique field violation
Example:
2026/02/02 15:45:14 Failed to create namespace: already_exists: resource unique field violation
exit status 1
Cause: You're trying to create a resource (namespace, attribute, subject mapping, etc.) that already exists on the platform. This commonly happens when running the quickstart examples multiple times.
Solution: This is expected behavior when re-running examples. You have several options:
-
Handle the error in your code (recommended): The complete examples in the language-specific quickstart guides show how to handle
already_existserrors gracefully by catching the error and fetching the existing resource instead. -
Deactivate or delete the existing resource:
Deactivate vs DeleteIn production environments, deactivate attributes instead of deleting them to preserve access to historical TDFs. Deletion is an unsafe operation that permanently removes the resource and can break decryption of existing TDFs.
Use delete only in development/testing contexts when you need to completely remove test data.
# List attributes to find the ID
otdfctl policy attributes list
# Deactivate the attribute (recommended - preserves historical TDFs)
otdfctl policy attributes deactivate --id <attribute-id>
# OR delete the attribute (development/testing only - unsafe operation)
otdfctl policy attributes unsafe delete --id <attribute-id> -
Do nothing: In some cases, failing when a resource already exists is the correct behavior. Not all code should be idempotent - sometimes you want to be alerted when attempting to create a duplicate resource.
Resource Not Found
Error: not_found: resource not found, attribute not found, or attribute does not exist
Cause: You're trying to use a resource (namespace, attribute, or attribute value) that doesn't exist on the platform. This commonly happens when an attribute FQN is passed to CreateTDF before the attribute has been created.
Prevention: Use ValidateAttributes before calling CreateTDF to catch missing attributes immediately instead of at decryption time. Available in all three SDKs:
- Go:
client.ValidateAttributes(ctx, fqns) - Java:
sdk.validateAttributes(fqns) - JavaScript:
await validateAttributes(platformUrl, authProvider, fqns)
Solution: Create the resource first using otdfctl or the SDK policy functions. For attributes, see the SDK Create Attribute function.
Quick fix using the CLI:
# Get the namespace ID (replace 'example.com' with your namespace)
export NAMESPACE_ID=$(otdfctl policy attributes list --json | jq -r '.attributes[0].namespace.id // empty')
# Create the attribute definition with initial values
otdfctl policy attributes create \
--name department \
--namespace $NAMESPACE_ID \
--rule ANY_OF \
--value finance \
--value engineering \
--value marketing
Alternatively, to add values after creating the attribute:
# Get the attribute ID for 'department' in your namespace
export DEPT_ATTRIBUTE_ID=$(otdfctl policy attributes list --json | jq -r '[.attributes[] | select(.name=="department" and .namespace.name=="<your-namespace>")][0].id')
# Add individual value(s)
otdfctl policy attributes values create --attribute-id $DEPT_ATTRIBUTE_ID --value marketing
Getting Help
If you can't resolve an issue using this guide, here are the next steps:
-
Check platform health — verify the platform is reachable and serving (see Connection Refused above). If the platform is down, resolve that first.
-
Search existing GitHub Discussions — many common questions are already answered in the opentdf/platform discussions.
-
Open a GitHub issue with:
- SDK language and version
- Full error message (including stack trace if available)
- Minimal code that reproduces the issue
- Platform version and how it's deployed