n8n-io/n8n · error · Error

Not authenticated — call login() first

Error message

Not authenticated — call login() first

What it means

The N8nClient.cookie getter returns sessionCookie for SSE auth, but throws if it was never set (no login). This is a fail-fast guard so SSE callers don't silently send requests with an undefined cookie and get 401s deep in the stream.

Solutions

  1. Call await client.login() before reading client.cookie.
  2. If reusing a client across a long lifespan, re-login when the cookie is missing.
  3. Guard callers with `if (!client.isAuthenticated) await client.login()`.

Example fix

// before: const sse = new SseClient(client.cookie, ...);
// after:  await client.login();
//        const sse = new SseClient(client.cookie, ...);
Defensive patterns

Strategy: validation

Validate before calling

if (!client.sessionCookie) await client.login();
const cookie = client.cookie; // safe after the guard

Prevention

When it happens

Trigger: Constructing an SSE client and reading `client.cookie` before calling login(); reusing a client after its session expired without re-login.

Common situations: Forgetting to login; refactoring that bypasses the login step; long-running processes whose cookie was cleared.

Understand the failure class

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/848de6538a370898. Report an issue: GitHub.

Appendix: source

Thrown at packages/@n8n/instance-ai/evaluations/clients/n8n-client.ts:991

		});
	}

	// -- SSE helpers ---------------------------------------------------------

	/**
	 * Build the SSE events URL for a given thread.
	 * Used by the SSE client to open a streaming connection.
	 */
	getEventsUrl(threadId: string): string {
		return `${this.baseUrl}/rest/instance-ai/events/${threadId}`;
	}

	/**
	 * Expose the session cookie so the SSE client can authenticate.
	 */
	get cookie(): string {
		if (!this.sessionCookie) {
			throw new Error('Not authenticated — call login() first');
		}
		return this.sessionCookie;
	}

	// -- Internal fetch ------------------------------------------------------

	private unwrapRestData<T>(result: unknown): T {
		if (result && typeof result === 'object' && 'data' in result) {
			return (result as { data: T }).data;
		}
		return result as T;
	}

	private async fetch(
		path: string,
		options: { method?: string; body?: unknown; timeoutMs?: number } = {},
	): Promise<unknown> {
		const headers: Record<string, string> = { 'Content-Type': 'application/json' };

View on GitHub (pinned to 5ac6606e81)