Skip to main content

    Troubleshooting

    ⚠️ This page documents the v1.x error taxonomy (BEHEST_AUTH_INVALID, BEHEST_RATE_LIMIT). The v1.5 SDK surfaces errors as typed classes (BehestAuthError, BehestRateLimitError, BehestQuotaError, etc.) with different semantics — see Error handling for the current taxonomy. The HTTP/CORS/DNS troubleshooting below is still accurate.

    Common issues and their resolutions. Every error response from Behest includes an X-Request-Id header — include this value when contacting support.


    "My API call returns 401"

    A 401 means authentication failed. Possible causes:

    Wrong or missing API key

    json
    {
      "error": {
        "code": "BEHEST_AUTH_INVALID",
        "message": "The provided API key is invalid."
      }
    }

    Check:

    1. Confirm your Authorization header is Bearer bh_live_YOUR_KEY with a space after Bearer.
    2. Confirm the key value — API keys are shown only once at creation. If you lost it, create a new one in the dashboard under your project's API Keys tab.
    3. Confirm the key has not been revoked. Deleted keys return 401 immediately.
    bash
    # Test with curl to isolate from SDK configuration
    curl -X POST https://{slug}.behest.app/v1/chat/completions \
      -H "Authorization: Bearer bh_live_YOUR_KEY" \
      -H "Content-Type: application/json" \
      -d '{"model": "gemini-2.5-flash", "messages": [{"role": "user", "content": "ping"}]}'

    No Authorization header

    json
    {
      "error": {
        "code": "BEHEST_AUTH_MISSING",
        "message": "No authentication provided."
      }
    }

    Include the header on every request. The @behest/client-ts SDK does this automatically.

    JWT expired

    json
    {
      "error": { "code": "BEHEST_AUTH_EXPIRED", "message": "Your JWT has expired." }
    }

    If you are managing JWTs manually (minting via POST /auth/v1/auth/mint), the token has a 24-hour TTL. Mint a new one. The SDK handles JWT management automatically — if you are seeing this error with the SDK, check that your system clock is synchronized (a clock skew greater than 5 minutes will cause premature expiration).


    "My API call returns 429"

    A 429 means rate limited or token budget exhausted.

    Rate limited

    json
    {
      "error": {
        "code": "BEHEST_RATE_LIMIT",
        "message": "Rate limit exceeded: 60/60 requests per minute."
      }
    }

    Resolution:

    1. Check the Retry-After response header — this is the number of seconds to wait before retrying.
    2. If you are consistently hitting rate limits, upgrade your plan at behest.ai/billing for higher RPM limits.
    3. Implement exponential backoff in your code:
      typescript
      import { sleep } from 'your-utils';
      try {
        const response = await client.chat.completions.create(...);
      } catch (error) {
        if (error instanceof OpenAI.APIError && error.status === 429) {
          const retryAfter = parseInt(error.headers?.['retry-after'] ?? '5', 10);
          await sleep(retryAfter * 1000);
          // retry
        }
      }

    Token budget exceeded

    json
    {
      "error": {
        "code": "BEHEST_BUDGET_EXCEEDED",
        "message": "Token budget exceeded for this billing period."
      }
    }

    Resolution:

    1. Check your token budget in project settings.
    2. Increase the tokens_per_day limit in project settings and deploy.
    3. Or upgrade your plan for higher limits.

    "I'm getting CORS errors"

    CORS errors appear in the browser console when your frontend origin is not in the project's allowed origins list. The error comes from the browser before the request reaches Behest, so you cannot see it in the Behest request logs.

    Symptoms:

    Access to fetch at 'https://{slug}.behest.app/v1/chat/completions'
    from origin 'https://your-app.com' has been blocked by CORS policy
    

    Resolution:

    Add your origin to the project's CORS settings:

    1. In the dashboard, open your project > Configuration > CORS Origins.
    2. Add https://your-app.com (no trailing slash).
    3. Save and Deploy.

    Or via API:

    bash
    curl -X PUT https://api.behest.app/v1/projects/$PROJECT_ID/settings \
      -H "Authorization: Bearer $TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"cors_origins": ["https://your-app.com"]}'
     
    curl -X POST https://api.behest.app/v1/projects/$PROJECT_ID/settings/deploy \
      -H "Authorization: Bearer $TOKEN"

    Wait up to 30 seconds after deploying for the gateway cache to refresh.

    During development: You can temporarily set cors_origins: ["*"] to allow all origins, but do not use this in production.


    "My provider key doesn't work"

    Format validation failure

    Behest validates provider key format when you save:

    • OpenAI keys must start with sk-
    • Anthropic keys must start with sk-ant-
    • Other providers have their own formats

    If the key does not match the expected format, the dashboard shows a validation error and does not save the key.

    Key saved but model still fails

    400: Configure your openai API key in Provider Settings to use gpt-4o
    

    This means the key is missing from Redis — it was not deployed after saving. Try:

    1. Re-save the provider key in Settings > Providers.
    2. In your project settings, re-select the model and click Deploy.

    Key is valid but the provider rejects it

    If the request reaches the provider but the provider rejects authentication, you will see a 502 BEHEST_PROVIDER_ERROR. Check that the key has not been revoked or rate-limited at the provider level (e.g., OpenAI billing limit exceeded).


    "PII Shield is blocking my requests"

    json
    {
      "error": {
        "code": "BEHEST_PII_BLOCKED",
        "message": "Request blocked: detected PII types ['CREDIT_CARD']"
      }
    }

    This means a message with a BLOCK action was detected in enforce mode.

    Options:

    1. Switch to shadow mode temporarily to allow traffic while you investigate:

      bash
      curl -X PUT https://api.behest.app/v1/projects/$PROJECT_ID/settings \
        -H "Authorization: Bearer $TOKEN" \
        -H "Content-Type: application/json" \
        -d '{"pii_mode": "shadow"}'
      curl -X POST https://api.behest.app/v1/projects/$PROJECT_ID/settings/deploy \
        -H "Authorization: Bearer $TOKEN"
    2. Change the action from BLOCK to MASK or REDACT for the entity type in question.

    3. Remove the entity from your pii_entities map if you do not want it scanned at all.

    4. Review the guardrail events to see which entity types are triggering:

      bash
      curl "https://api.behest.app/v1/tenants/$TENANT_ID/guardrails/events?type=pii_block&project_id=$PROJECT_ID" \
        -H "Authorization: Bearer $TOKEN"

    Presidio uses a confidence threshold of 0.7. If legitimate content is being flagged, review the event log to see the entity types and check whether the content contains patterns that look like PII (e.g., formatted phone numbers, email-like strings).


    "I can't find my project's FQDN"

    Each project gets two FQDNs provisioned by Google Cloud DNS:

    • {slug}.dev.internal.behest.ai
    • {slug}.prod.internal.behest.ai

    These are visible in the project settings. However, DNS propagation is asynchronous and takes a few minutes after project creation. The project's dns_status field reflects the current state:

    StatusMeaning
    PENDINGDNS job is queued but not yet processed
    PROVISIONEDDNS record has been created
    FAILEDDNS job failed — contact support

    For development use, route requests via the main API gateway (https://api.behest.app/v1) with your API key. The project-specific FQDN is used for advanced routing scenarios and is not required for standard API calls.


    "Settings saved but not taking effect"

    Guardrail settings, model changes, and other project configuration require an explicit Deploy step to become active.

    1. Confirm you clicked Deploy (not just Save) in the dashboard.
    2. Wait up to 30 seconds — that is the Redis cache TTL at the Kong gateway.
    3. If changes still have not taken effect after 30 seconds, try deploying again.

    Via API, saving (PUT) and deploying are separate calls:

    bash
    # Save
    curl -X PUT https://api.behest.app/v1/projects/$PROJECT_ID/settings ...
     
    # Deploy (required to activate)
    curl -X POST https://api.behest.app/v1/projects/$PROJECT_ID/settings/deploy \
      -H "Authorization: Bearer $TOKEN"

    Health Check Endpoints

    Behest's internal services expose health and readiness probes. These are useful for monitoring integrations and for Kubernetes liveness/readiness probes.

    ServiceHealth endpointReadiness endpoint
    redis-sync-workerGET /healthzGET /readyz
    behest-authGET /healthz

    The health endpoint returns 200 OK with {"status": "ok"} when the service is running. The readiness endpoint returns 200 OK when the service has completed its startup initialization (database connection, Redis connection, initial sync).

    These endpoints are internal and not exposed through the public API gateway.


    Getting Help

    GitHub Issues

    Report bugs, unexpected behavior, or documentation issues at: github.com/behest-ai/behest-portal/issues

    Include:

    • The X-Request-Id header value from the failing request
    • The error response body
    • The request you sent (without your API key)
    • Your project slug (not your API key)

    Community Discord

    Ask questions, share what you are building, and get help from the community and the Behest team: discord.gg/behest

    Support Email

    For account issues, billing questions, or security concerns: support@behest.ai

    For enterprise support or guided onboarding, contact: enterprise@behest.ai

    Enterprise Token FinOps: Enforce hard budgets and attribute costs per session.

    Learn more