CherryHQ/cherry-studio · error · Error

DMXAPI provider requires a non-empty `baseURL`. An empty val

Error message

DMXAPI provider requires a non-empty `baseURL`. An empty value would resolve fetch paths against the renderer process origin (app://, file://) and surface as opaque "Failed to fetch" errors.

What it means

Thrown by `createDmxapiProvider` when `settings.baseURL` is falsy. Same Electron-origin rationale as the DashScope guard: an empty base would resolve fetch paths against the renderer origin (`app://`, `file://`) and surface as opaque "Failed to fetch" errors. Failing fast with an explicit message is preferred.

Source

Thrown at src/main/ai/provider/custom/dmxapi/dmxapiProvider.ts:110

 * re-resolved provider settings.
 */
export function buildDmxapiTransport(settings: DmxapiProviderSettings): ImageGenerationTransport {
  const chatBaseURL = settings.endpointBaseURLs?.[ENDPOINT_TYPE.OPENAI_CHAT_COMPLETIONS] ?? settings.baseURL
  if (!chatBaseURL) {
    throw new Error('DMXAPI provider requires a non-empty `baseURL` to build the image transport.')
  }
  return createDmxapiTransport({
    apiKey: settings.apiKey ?? '',
    // The transport POSTs to host-root paths (`/v1/images/...`), so strip the
    // OpenAI-compat version suffix from the chat baseURL to avoid a double `/v1`.
    baseURL: withoutTrailingApiVersion(chatBaseURL)
  })
}

export function createDmxapiProvider(settings: DmxapiProviderSettings = {}): DmxapiProvider {
  const { baseURL, fetch: customFetch } = settings
  if (!baseURL) {
    throw new Error(
      'DMXAPI provider requires a non-empty `baseURL`. An empty value would resolve fetch paths against the renderer process origin (app://, file://) and surface as opaque "Failed to fetch" errors.'
    )
  }

  const resolveApiKey = () =>
    loadApiKey({ apiKey: settings.apiKey, environmentVariableName: 'DMXAPI_API_KEY', description: 'DMXAPI' })

  const compatHeaders = () => ({
    Authorization: `Bearer ${resolveApiKey()}`,
    ...settings.headers
  })

  const chatBaseURL = settings.endpointBaseURLs?.[ENDPOINT_TYPE.OPENAI_CHAT_COMPLETIONS] ?? baseURL
  const compatUrl = ({ path }: { path: string; modelId: string }) => `${withoutTrailingSlash(chatBaseURL)}${path}`
  const nativeBaseURL = withoutTrailingApiVersion(baseURL)
  const anthropicBaseURL =
    settings.endpointBaseURLs?.[ENDPOINT_TYPE.ANTHROPIC_MESSAGES] ?? formatApiHost(nativeBaseURL, true)
  const geminiBaseURL =

View on GitHub (pinned to 726446b54c)

Solutions

  1. Set `baseURL` on the DMXAPI provider settings to the gateway host, e.g. `https://www.dmxapi.cn/v1`.
  2. Confirm the provider config builder passes the host through from user settings.
  3. Note: `endpointBaseURLs` supplements but does not replace `baseURL` for the factory guard.

Example fix

// before
createDmxapiProvider({ apiKey: 'sk-...' })
// after
createDmxapiProvider({ apiKey: 'sk-...', baseURL: 'https://www.dmxapi.cn/v1' })
Defensive patterns

Strategy: validation

Validate before calling

function assertDmxapiSettings(s: { baseURL?: string }) {
  if (!s.baseURL) throw new Error('DMXAPI baseURL required before creating provider')
}
assertDmxapiSettings(settings)
const provider = createDmxapiProvider(settings)

Type guard

const hasDmxapiBaseURL = (s: { baseURL?: string }): s is { baseURL: string } =>
  typeof s.baseURL === 'string' && s.baseURL.trim().length > 0

Prevention

When it happens

Trigger: Instantiating the DMXAPI provider with no `baseURL` — `createDmxapiProvider({})` or `createDmxapiProvider({ baseURL: '' })`.

Common situations: DMXAPI provider added in settings but the API host left blank; a migration reset the field; the user configured `endpointBaseURLs` only and expected the factory to infer a host.

Related errors


AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12). Data as JSON: /api/errors/2c12c202b9037384. Report an issue: GitHub.