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 guards the x-api-key header so it can only be set through the dedicated setApiKey() (or init({ apiKey })) entry point. setHeader and setHeaders route every key through assertNoApiKey, which throws a plain Error when the lowercased key equals x-api-key. This prevents callers from accidentally bypassing the key-management path or overwriting the API key with an unrelated header value.

Source

Thrown at packages/sdk/src/index.ts:47

};

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 getAssetOriginalPath = (id: string) => `/assets/${id}/original`;

export const getAssetThumbnailPath = (id: string) => `/assets/${id}/thumbnail`;

export const getAssetPlaybackPath = (id: string) =>
  `/assets/${id}/video/playback`;

export const getUserProfileImagePath = (userId: string) =>
  `/users/${userId}/profile-image`;

export const getPeopleThumbnailPath = (personId: string) =>
  `/people/${personId}/thumbnail`;

View on GitHub (pinned to 199723261c)

Solutions

  1. Call setApiKey(apiKey) instead of setting the header yourself.
  2. If using init(), pass the key via the apiKey field and keep headers free of x-api-key.
  3. Filter the x-api-key key out of any dynamic header object before calling setHeaders.

Example fix

// before
setHeaders({ 'x-api-key': apiKey, 'accept': 'application/json' });
// after
setApiKey(apiKey);
setHeaders({ 'accept': 'application/json' });
Defensive patterns

Strategy: validation

Validate before calling

// before calling setHeaders, strip any api-key variant
const SAFE_HEADERS = Object.fromEntries(
  Object.entries(headers).filter(
    ([k]) => k.toLowerCase() !== 'x-api-key',
  ),
);
setHeaders(SAFE_HEADERS);
setApiKey(apiKey);

Type guard

const isApiKeyHeader = (key: string): boolean =>
  key.toLowerCase() === 'x-api-key';

Try / catch

try {
  setHeaders(headers);
} catch (e) {
  if ((e as Error).message.includes('setApiKey')) {
    setApiKey(headers['x-api-key']);
    const { 'x-api-key': _omit, ...rest } = headers;
    setHeaders(rest);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling setHeaders({ 'x-api-key': '...' }), setHeaders({ 'X-API-KEY': '...' }), setHeader('X-Api-Key', value), or passing headers: { 'x-api-key': ... } to init(). The check is case-insensitive, so any capitalization triggers it.

Common situations: Migrating from a custom fetch wrapper where you set auth headers manually; copy-pasting a header object that includes the api key; trying to override the key per-request via setHeaders.

Related errors


AI-assisted analysis of immich-app/immich@199723261c (2026-08-12). Data as JSON: /api/errors/0455d7731b437bce. Report an issue: GitHub.