n8n-io/n8n · error · Error

User permanently denied access to ${resource.toolGroup}: ${r

Error message

User permanently denied access to ${resource.toolGroup}: ${resource.resource}

What it means

Thrown by checkPermissions() when session.check() returns 'deny' — the user previously chose 'alwaysDeny' for this exact toolGroup + resource combination and that decision was persisted in the gateway session. The tool call is aborted before execution begins. This is a hard deny from a prior persistent user decision, not a new prompt.

Source

Thrown at packages/@n8n/computer-use/src/gateway-client.ts:501

		};

		const resources = await def.getAffectedResources(typedArgs, context);
		await this.checkPermissions(resources, decision);

		return await def.execute(typedArgs, context);
	}

	private async checkPermissions(
		resources: AffectedResource[],
		decision?: ResourceDecision,
	): Promise<void> {
		const { session, confirmResourceAccess, config } = this.options;

		for (const resource of resources) {
			const rule = session.check(resource.toolGroup, resource.resource);

			if (rule === 'deny') {
				throw new Error(
					`User permanently denied access to ${resource.toolGroup}: ${resource.resource}`,
				);
			}

			if (rule === 'allow') continue;

			let resolvedDecision: ResourceDecision;

			if (decision && config.permissionConfirmation === 'instance') {
				resolvedDecision = decision;
			} else if (config.permissionConfirmation === 'instance') {
				throw new Error(
					`${GATEWAY_CONFIRMATION_REQUIRED_PREFIX}${JSON.stringify({
						toolGroup: resource.toolGroup,
						resource: resource.resource,
						description: resource.description,
						options: INSTANCE_RESOURCE_DECISION_KEYS,
					})}`,

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Reset or restart the gateway session to clear persistent deny rules
  2. Request a different resource path that is not under a deny rule
  3. Ask the user to re-approve access by clearing the deny rule in the session
Defensive patterns

Strategy: validation

Validate before calling

function isResourceDenied(session: GatewaySession, toolGroup: string, resource: string): boolean {
  return session.check(toolGroup as ToolGroup, resource) === 'deny';
}

// Check before calling the tool:
if (isResourceDenied(session, 'filesystemRead', resolvedPath)) {
  throw new Error('This resource is permanently denied. Reset the session to re-approve.');
}

Type guard

function isPermanentDenyError(e: unknown): boolean {
  return e instanceof Error && e.message.startsWith('User permanently denied access to');
}

Try / catch

try {
  await gatewayClient.callTool(name, args);
} catch (e) {
  if (e instanceof Error && e.message.startsWith('User permanently denied access to')) {
    // Session has a persistent deny rule. Reset session or use a different resource.
    session.reset(); // clear persistent rules
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: The user previously selected 'alwaysDeny' for a resource (e.g. a specific file path or browser domain) and the same resource is requested again in the same session. The session rule short-circuits to 'deny' without prompting.

Common situations: User denied persistent access to a file or directory and the agent tries to access the same resource again in a later tool call within the same session.

Related errors


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