n8n-io/n8n · error · Error
Could not determine personal project ID
Error message
Could not determine personal project ID
What it means
getPersonalProjectId GETs /rest/projects/personal and expects result.data.id. If the response is missing data.id, the client cannot address project-scoped resources (data tables, etc.). Usually a sign the call was unauthenticated, the user has no personal project, or the response shape changed.
Source
Thrown at packages/@n8n/instance-ai/evaluations/clients/n8n-client.ts:833
): Promise<void> {
await this.fetch('/rest/instance-ai/eval/seed-data-table-rows', {
method: 'POST',
body: { threadId, tableId, rows },
});
}
// -- Data tables ---------------------------------------------------------
/**
* Get the personal project ID for the authenticated user.
* GET /rest/projects/personal
*/
async getPersonalProjectId(): Promise<string> {
const result = (await this.fetch('/rest/projects/personal')) as {
data: { id: string };
};
if (!result.data?.id) {
throw new Error('Could not determine personal project ID');
}
return result.data.id;
}
/**
* List data tables in a project.
* GET /rest/projects/:projectId/data-tables
*/
async listDataTables(projectId: string): Promise<Array<{ id: string; name: string }>> {
// The list endpoint paginates: `{ data: { count, data: [...] } }`. Reading
// `result.data` as the array made this return [] for every project, silently —
// it has no error path, so every caller just saw "no tables".
//
// `take` is explicit because the default page is 10, and every caller here
// enumerates the WHOLE set (seed eviction, CU cleanup, discovery's pre-existing
// set) — a short page silently leaves leftovers behind. 250 is the server's
// per-page cap; a case declares at most 20 tables and eviction runs before
// every build, so the backlog drains rather than outgrowing one page.View on GitHub (pinned to 5ac6606e81)
Solutions
- Ensure login() (or acceptInvitation) completed and the cookie is set before calling getPersonalProjectId.
- Confirm the user has a personal project (create/finish onboarding if not).
- Inspect the raw /rest/projects/personal response to verify the envelope shape.
Defensive patterns
Strategy: validation
Validate before calling
if (!client.sessionCookie) throw new Error('not logged in');
const r = (await client.fetch('/rest/projects/personal')) as { data?: { id?: string } };
if (!r.data?.id) throw new Error('no personal project; finish user onboarding'); Type guard
const hasPersonalProject = (v: unknown): v is { data: { id: string } } =>
typeof v === 'object' && v !== null && typeof (v as any)?.data?.id === 'string'; Try / catch
try { return await client.getPersonalProjectId(); }
catch (e) {
if (e instanceof Error && e.message.includes('personal project')) { /* re-login or provision user */ }
else throw e;
} Prevention
- Always login before calling project endpoints.
- Ensure the user finished onboarding so a personal project exists.
- Inspect the raw envelope when integrating with a new backend version.
When it happens
Trigger: Calling getPersonalProjectId before login(); user provisioning incomplete so no personal project exists; backend version with a different response envelope.
Common situations: Forgetting to await login(); freshly invited user whose project wasn't provisioned; proxy returning an error envelope without data.
Related errors
- Failed to authenticate with n8n — no session cookie received
- MCP api-key rotate endpoint returned no apiKey
- MCP api-key rotate endpoint returned a redacted key — cannot
- Invitation accepted but no session cookie received
- Not authenticated — call login() first
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/893d3038d5a18b4c.
Report an issue: GitHub.