immich-app/immich · error · Error
The API key header can only be set using setApiKey().
Error message
The API key header can only be set using setApiKey().
What it means
The Immich SDK reserves the 'x-api-key' header for setApiKey() only. setHeader/setHeaders refuse any attempt to set a header named x-api-key (case-insensitive) so the credential can't be duplicated or overridden inconsistently by user code.
Solutions
- Remove the x-api-key header from setHeader/setHeaders calls and call setApiKey(value) instead.
- Filter x-api-key out of any header object sourced from config/env before passing to setHeaders.
- Rename the env/config field so it feeds setApiKey, not a generic header list.
Example fix
// before
sdk.setHeaders({ 'x-api-key': process.env.IMMICH_API_KEY! });
// after
sdk.setApiKey(process.env.IMMICH_API_KEY!); Defensive patterns
Strategy: validation
Validate before calling
const RESERVED = ['x-api-key']; const safeHeaders = Object.fromEntries( Object.entries(userHeaders).filter(([k]) => !RESERVED.includes(k.toLowerCase())) ); sdk.setHeaders(safeHeaders);
Try / catch
try {
sdk.setHeaders(headers);
} catch (e) {
if (String(e).includes('setApiKey')) {
sdk.setApiKey((headers as any)['x-api-key']);
} else throw e;
} Prevention
- Always supply credentials via setApiKey(), never via generic header maps
- Strip reserved auth headers from config/env-derived header objects
- When porting raw fetch code, migrate x-api-key usage to setApiKey first
When it happens
Trigger: Calling sdk.setHeader('x-api-key', ...) or passing { 'x-api-key': ... } (any casing: X-API-Key, etc.) to setHeaders; commonly done by users who treat the SDK like raw fetch and copy auth-header code from curl examples.
Common situations: Migrating code from a plain fetch wrapper to the Immich SDK, wiring headers from environment config that already contains the key, or bulk-copying a defaults.headers object that includes x-api-key.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Invalid API key
- Authentication required
- authToken is required
- Expected a JSON response
- Failed login attempt for user
AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15).
Data as JSON: /api/errors/0455d7731b437bce.
Report an issue: GitHub.
Appendix: source
Thrown at packages/sdk/src/index.ts:48
};
export const setHeader = (key: string, value: string) => {
assertNoApiKey(key);
defaults.headers = defaults.headers || {};
defaults.headers[key] = value;
};
export const setHeaders = (headers: Record<string, string>) => {
defaults.headers = defaults.headers || {};
for (const [key, value] of Object.entries(headers)) {
assertNoApiKey(key);
defaults.headers[key] = value;
}
};
const assertNoApiKey = (headerKey: string) => {
if (headerKey.toLowerCase() === 'x-api-key') {
throw new Error('The API key header can only be set using setApiKey().');
}
};
export const jsonOnly =
(impl?: typeof fetch): typeof fetch =>
async (input, options) => {
const response = await (impl ?? fetch)(input, options);
const expectsJson = new Headers(options?.headers)
.get('accept')
?.includes('json');
if (!expectsJson || response.status === 204) {
return response;
}
const contentType = response.headers.get('content-type');
if (!contentType?.includes('json')) {
throw new MalformedResponseError(View on GitHub (pinned to e55ac299a4)