Skip to content

AI Chat: Custom endpoint fails with "Invalid API key" when OpenAI key is empty — wrong credential resolved for custom+openai provider #2369

Description

@xtraxion

Bug Summary

When a Custom OpenAI-compatible API endpoint (e.g. local LLM, proxy, Manifest) is configured via gptBaseUrl + gptBaseUrlKey, the AI Inline Completion and Chat features fail with "Invalid API key (401)" even though the Endpoint-Test button succeeds. The root cause is that the frontend sends provider: "openai" for custom endpoints, but the backend resolves credentials from gptKey instead of gptBaseUrlKey.

Steps to Reproduce

  1. Leave the "OpenAI / ChatGPT API key" (gptKey) empty.
  2. Enter a "Custom API Base URL" (e.g. http://192.168.1.10:11434/v1).
  3. Enter a valid "Custom API key" (gptBaseUrlKey, e.g. mnfst_xxx for Manifest).
  4. Save the adapter config and restart.
  5. Open the JavaScript editor → click the AI Chat button.
  6. Observe: Endpoint test returns "ok", but actual chat/completion returns "Invalid API key (401)".

Expected Behavior

When gptBaseUrl is configured and gptBaseUrlKey contains a key, the adapter should use gptBaseUrlKey for requests sent to that custom base URL, not gptKey.

Actual Behavior

The frontend (AiInlineProvider-CaHd2G2Q.js) maps provider: "custom" → provider: "openai" + baseUrl.

let providers = ['custom','openai','deepseek','anthropic','gemini'];
for (let e of providers) {
    let t = n.providers.find(t => t.provider === e);
    if (t) {
        d = e === 'custom' ? 'openai' : e;  // "custom" becomes "openai"
        f = t.baseUrl || '';
        break;
    }
}

The backend (aiProviderResolver.ts / build/lib/aiProviderResolver.js) then resolves credentials based on provider:

const PROVIDER_KEY_FIELD = {
    openai: 'gptKey',          // ← wrong field for custom endpoint
    anthropic: 'claudeKey',
    gemini: 'geminiKey',
    deepseek: 'deepseekKey',
    custom: 'gptBaseUrlKey',   // ← never reached
};

Since provider === 'openai' and gptKey is empty, the adapter sends an empty or wrong API key to the custom endpoint, resulting in 401.

Environment

  • Adapter: ioBroker.javascript v10.1.3
  • Node.js: v24.x (also reproducible on v22)
  • Credential mode: both manual and manager affected

Workaround

As a workaround, enter the Custom API key into the "OpenAI / ChatGPT API key" field (gptKey) instead of the "Custom API key" field (gptBaseUrlKey). This works because the backend treats custom endpoints as provider: 'openai' and reads from gptKey. However, this makes it impossible to use both OpenRouter (or real OpenAI) and a custom endpoint simultaneously, because both would share the same gptKey field.

Suggested Fix

Option A: In aiProviderResolver.resolveProviderCredentials, check if a custom baseUrl is present alongside provider === 'openai'. If so, prefer gptBaseUrlKey over gptKey.

Option B: Preserve provider: 'custom' through the entire flow instead of rewriting it to 'openai' in the frontend. Then the backend naturally resolves gptBaseUrlKey.

Option C: Add a dedicated provider type mapping: when baseUrl is set and differs from the default OpenAI URL, automatically use the custom credentials.

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions