immich-app/immich · error · UnauthorizedException

Elevated permission is required

Error message

Elevated permission is required

What it means

An UnauthorizedException (HTTP 401) thrown by requireElevatedPermission when the session on the auth context does not have hasElevatedPermission set. Elevated permission is granted after a recent PIN/password re-authentication and is required for sensitive operations; a session that has not been elevated (or whose elevation expired) is rejected.

Source

Thrown at server/src/utils/access.ts:339

    case Permission.StackDelete: {
      return access.stack.checkOwnerAccess(auth.user.id, ids);
    }

    case Permission.WorkflowRead:
    case Permission.WorkflowUpdate:
    case Permission.WorkflowDelete: {
      return access.workflow.checkOwnerAccess(auth.user.id, ids);
    }

    default: {
      return new Set<string>();
    }
  }
};

export const requireElevatedPermission = (auth: AuthDto) => {
  if (!auth.session?.hasElevatedPermission) {
    throw new UnauthorizedException('Elevated permission is required');
  }
};

View on GitHub (pinned to 199723261c)

Solutions

  1. Drive the PIN/password step-up flow to set hasElevatedPermission on the session before retrying the operation.
  2. Re-run the elevation flow if the elevated state has expired.
  3. Ensure a PIN is configured for the user if the flow requires it.
  4. In tests, perform the elevation request after login before calling elevated endpoints.

Example fix

// before
await api.deleteSensitiveThing(id); // 401 'Elevated permission is required'

// after
await api.unlockWithPin(userPin); // sets hasElevatedPermission on session
await api.deleteSensitiveThing(id);
Defensive patterns

Strategy: validation

Validate before calling

function hasElevated(auth) {
  return Boolean(auth?.session?.hasElevatedPermission);
}
if (!hasElevated(auth)) {
  await api.unlockWithPin(pin); // step-up
}
if (!hasElevated(auth)) {
  return unauthorized('Elevated permission required');
}

Type guard

const isElevatedPermissionError = (e: unknown): boolean =>
  typeof e === 'object' && e !== null && (e as any).status === 401 && (e as any).message === 'Elevated permission is required';

Try / catch

try {
  await api.doSensitiveOp(id);
} catch (e) {
  if (isElevatedPermissionError(e)) {
    await promptPinAndUnlock();
    return api.doSensitiveOp(id); // retry once after step-up
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling a route guarded by requireElevatedPermission without first completing the PIN/password step-up flow, or after the elevated state has timed out on the session.

Common situations: User logged in normally but the operation requires step-up auth; elevated permission expired mid-session; PIN not configured; integration tests that authenticate but skip the elevation step.

Related errors


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