CherryHQ/cherry-studio · error · Error
PPIO provider requires a non-empty `baseURL`. An empty value
Error message
PPIO 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
Identical fail-fast guard to the OVMS one, applied in createPpioProvider(): an empty settings.baseURL would make the OpenAI-compatible SDK resolve fetch paths against the renderer origin, surfacing as opaque 'Failed to fetch'. The throw at construction replaces that with an explicit, attributable error.
Source
Thrown at src/main/ai/provider/custom/ppio/ppioProvider.ts:53
*/
export function buildPpioTransport(settings: PpioProviderSettings): ImageGenerationTransport {
return createPpioTransport({
apiKey: settings.apiKey ?? '',
baseURL: settings.imageBaseURL || DEFAULT_PPIO_BASE_URL
})
}
/**
* Unified PPIO provider — chat, embedding, and image off one `ProviderV3`,
* mirroring `newapi-provider.ts`. Chat/embedding go through the OpenAI-
* compatible SDK aimed at `settings.baseURL`; the image model keeps its
* bespoke submit/poll behavior via `createImageGenerationModel + createPpioTransport`
* aimed at `settings.imageBaseURL` (defaults to `DEFAULT_PPIO_BASE_URL`).
*/
export function createPpioProvider(settings: PpioProviderSettings = {}): PpioProvider {
const { baseURL, fetch: customFetch } = settings
if (!baseURL) {
throw new Error(
'PPIO 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: 'PPIO_API_KEY', description: 'PPIO' })
const authHeaders = () => ({
Authorization: `Bearer ${resolveApiKey()}`,
...settings.headers
})
const url = ({ path }: { path: string; modelId: string }) => `${withoutTrailingSlash(baseURL)}${path}`
const createChatModel = (modelId: string) =>
new OpenAICompatibleChatLanguageModel(modelId, {
provider: `${PPIO_PROVIDER_NAME}.chat`,
url,View on GitHub (pinned to 726446b54c)
Solutions
- Set a non-empty PPIO host (e.g. https://api.ppinfra.com/v3/openai) before constructing the provider.
- Read the host from Preference/BootConfig before calling createPpioProvider.
- Mark the baseURL field required in the provider UI.
- Defer provider construction until settings are populated; do not instantiate with a blank host.
Example fix
// before
const provider = createPpioProvider({ baseURL: settings.ppio?.baseURL })
// after
if (!settings.ppio?.baseURL) throw new Error('PPIO API host is required')
const provider = createPpioProvider({ baseURL: settings.ppio.baseURL }) Defensive patterns
Strategy: validation
Validate before calling
if (!settings.baseURL) {
throw new Error('PPIO API host is required (e.g. https://api.ppinfra.com/v3/openai)')
}
const provider = createPpioProvider(settings) Type guard
export function isPpioBaseURLError(e: unknown): boolean {
return e instanceof Error && /PPIO provider requires a non-empty `baseURL`/.test(e.message)
} Try / catch
try {
createPpioProvider(settings)
} catch (e) {
if (isPpioBaseURLError(e)) {
// prompt the user for the PPIO host before retrying
}
throw e
} Prevention
- Make the PPIO host field required in the provider UI.
- Read host from settings before constructing the provider.
- Remember imageBaseURL has its own default; this guard only covers chat/embedding.
When it happens
Trigger: createPpioProvider({}) or createPpioProvider({ baseURL: '' }) — PPIO provider instantiated without a chat/embedding host. Note: imageBaseURL has its own default (DEFAULT_PPIO_BASE_URL), so the image path is unaffected; this guard is specifically about the chat/embedding baseURL.
Common situations: User adds a PPIO provider but leaves the API host blank, settings migration leaves baseURL undefined, or programmatic construction without the host.
Related errors
- OVMS provider requires a non-empty `baseURL`. An empty value
- Either baseUrl or command must be provided
- DashScope provider requires a non-empty `baseURL`. An empty
- DMXAPI provider requires a non-empty `baseURL` to build the
- DMXAPI provider requires a non-empty `baseURL`. An empty val
AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12).
Data as JSON: /api/errors/b9353c0f772e8dac.
Report an issue: GitHub.