chatboxai/chatbox · error · Error
pdf_password_protected
pdf_password_protected
Error message
pdf_password_protected
What it means
Thrown by CustomClaude.listModels() when GET `${apiHost}/models?limit=990` returns a body without a top-level `data` array. Identical shape-guard to the built-in Claude provider, but here the host is a user-supplied `apiHost` (a custom Anthropic-compatible endpoint) and the request is sent through the optional proxy with a fixed `x-api-key` header. The missing `data` field means the custom endpoint is not speaking the Anthropic `/v1/models` schema.
Source
Thrown at src/main/file-parser.ts:243
}
}
if (pageTexts.every((text) => text === '')) {
// No extractable text (e.g. a scanned PDF) — keep returning an empty string
// instead of a list of bare page markers.
return ''
}
log.info(`Parsed PDF ${filePath}: ${document.numPages} pages`)
return pageTexts.map((text, i) => `${formatPdfPageMarker(i + 1)}\n\n${text}`).join('\n\n')
} catch (error) {
// pdfjs throws a typed PasswordException for encrypted PDFs. Surface it as a
// distinct code so the user is told the PDF needs a password instead of the
// generic "unsupported file" message (and so the cloud fallback, which also
// cannot read it, is skipped). Per-page failures are handled inside the loop
// and never reach here.
if (error instanceof Error && error.name === 'PasswordException') {
throw new Error(LOCAL_PARSER_PDF_PASSWORD_PROTECTED_ERROR)
}
throw error
} finally {
await loadingTask.destroy()
}
}
export async function parseEpub(filePath: string): Promise<string> {
return new Promise((resolve, reject) => {
const epub = new Epub(filePath)
epub.on('error', (error) => {
log.error('EPUB parsing error:', error)
reject(error)
})
epub.on('end', async () => {
try {View on GitHub (pinned to 81571269ad)
Solutions
- Confirm the custom host actually implements the Anthropic `/v1/models` endpoint with `{ data: [{ id, type }] }` — many Claude relays only proxy chat.
- Read the JSON.stringify'd payload inside the ApiError message: an `error.type` of `authentication_error` means bad key; an `overloaded_error` is transient; an object with `models` instead of `data` means wrong schema.
- Set `apiHost` to the base origin only (e.g. `https://relay.example.com`), no `/v1` suffix — normalizeClaudeHost appends the version path.
- If the relay is OpenAI-style, switch the provider type from 'Custom Claude' to a generic Custom OpenAI provider.
Example fix
// before: relay returns { models: [...] }
// after: either expose /v1/models with Anthropic schema, or define models manually
async listModels() {
try { return await super.listModels() }
catch (e) {
if (e instanceof ApiError) return [{ modelId: this.options.model.modelId, type: 'chat' }]
throw e
}
} Defensive patterns
Strategy: try-catch
Validate before calling
async function probeCustomClaudeModels(host: string, key: string): Promise<boolean> {
const res = await fetch(`${host}/models?limit=990`, {
headers: { 'anthropic-version': '2023-06-01', 'x-api-key': key }
})
const json = await res.json().catch(() => ({}))
return Array.isArray((json as any)?.data)
} Type guard
function isAnthropicModelsResponse(json: unknown): json is { data: { id: string; type: string }[] } {
return typeof json === 'object' && json !== null && Array.isArray((json as any).data)
} Try / catch
try { return await customClaude.listModels() }
catch (e) {
if (e instanceof ApiError) return [{ modelId: customClaude.options.model.modelId, type: 'chat' }]
throw e
} Prevention
- When adding a Custom Claude provider, probe /models during setup and warn if the schema is wrong.
- Document that Custom Claude relays must implement the Anthropic /v1/models route, not OpenAI /v1/models.
- Trim apiHost and strip any trailing /v1 to avoid double-prefixed URLs.
When it happens
Trigger: A custom provider configured with an OpenAI-compatible base URL mistaken for an Anthropic-compatible one (returns `{ data: [...] }` is actually correct for Anthropic, but an OpenAI proxy returning `{ models: [...] }` fails); `apiHost` includes a trailing `/v1` or a path segment so the constructed URL is malformed; `apiKey` is wrong and the upstream returns `{ type: 'error', error: { ... } }`; the proxy rewrites the response into HTML or a generic error envelope.
Common situations: User adds a 'Custom Claude' provider pointing at a relay that only implements `/v1/messages` (chat) but not `/v1/models`; apiHost pasted with a trailing slash or `/v1` suffix that normalizeClaudeHost then double-prefixes; key from a different vendor reused; reverse proxy (nginx/cloudflare) returns a 502 HTML page that res.json() parses to `{}` or throws.
Related errors
- local_parser_file_too_large
- knowledge_base_parsed_content_too_large
- No content extracted from file
- Failed to search knowledge base (id: ${kbId}). Please try ag
- Invalid knowledge base ID
AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12).
Data as JSON: /api/errors/1621ee5c945bb58e.
Report an issue: GitHub.