Skip to main content

SDK Troubleshooting

This guide covers common issues when working with the OpenTDF SDKs and how to resolve them.

Troubleshooting Scope

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:

  1. Re-authenticate (CLI):

    otdfctl auth client-credentials <client-id> <client-secret>
  2. Implement token refresh in your application: The JavaScript SDK's refreshAuthProvider handles 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
    });
  3. 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:

  1. 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\Root

    Obtain the CA certificate from your platform administrator or deployment documentation.

  2. Restart your browser and terminal after trusting the certificate — applications must reload their certificate stores to pick up the change.

  3. 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:

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:

  • PermissionDenied or forbidden
  • rewrap request 403
  • permission_denied: request error

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:

  1. Re-encrypt the original file — if you have access to the plaintext, create a fresh TDF
  2. Check SDK version compatibility — the SDK used to decrypt must support the TDF format version used to encrypt (e.g., TDF3 vs nanoTDF)
  3. Verify file integrity — TDFs are tamper-evident; any modification after encryption will cause decryption to fail
  4. 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:

  1. Handle the error in your code (recommended): The complete examples in the language-specific quickstart guides show how to handle already_exists errors gracefully by catching the error and fetching the existing resource instead.

  2. Deactivate or delete the existing resource:

    Deactivate vs Delete

    In 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>
  3. 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:

  1. Check platform health — verify the platform is reachable and serving (see Connection Refused above). If the platform is down, resolve that first.

  2. Search existing GitHub Discussions — many common questions are already answered in the opentdf/platform discussions.

  3. 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