toeverything/AFFiNE · error · ActionForbidden
action_forbidden
action_forbidden
Error message
Copilot is disabled.
What it means
Guard in the copilot plugin's availability helper: any copilot feature route rejects with ActionForbidden when config.copilot.enabled is false. It is the single choke point that keeps every AI endpoint unavailable until an operator flips the copilot.enabled config item, so hitting it means the feature flag is off on this deployment, not a per-user permission problem.
Source
Thrown at packages/backend/server/src/plugins/copilot/availability.ts:6
import type { Config } from '../../base/config';
import { ActionForbidden } from '../../base/error/errors.gen';
export function assertCopilotEnabled(config: Config) {
if (!config.copilot.enabled) {
throw new ActionForbidden('Copilot is disabled.');
}
}
View on GitHub (pinned to b4c8548c09)
Solutions
- Set the copilot.enabled config item to true (e.g. AFFINE_COPILOT_ENABLED=true or the equivalent config source) and restart the server.
- Verify with a config dump / diagnostics endpoint that copilot.enabled actually reads true after restart.
- On the client, gate AI UI behind the server-advertised copilot availability so users never reach the endpoint.
Example fix
# before (env) AFFINE_COPILOT_ENABLED=false # after AFFINE_COPILOT_ENABLED=true
Defensive patterns
Strategy: validation
Validate before calling
// Client: check advertised availability before calling copilot APIs
const { copilotEnabled } = await client.getServerCapabilities();
if (!copilotEnabled) disableAiFeatures(); Try / catch
try {
await copilotApi.chat(...);
} catch (e) {
if (e?.code === 'action_forbidden' && /copilot is disabled/i.test(e.message)) {
showSetupNotice('Ask the admin to enable copilot (AFFINE_COPILOT_ENABLED=true)');
} else throw e;
} Prevention
- Enable the copilot plugin in config before deploying any AI-dependent feature.
- Expose and consume a capability flag so clients never call disabled endpoints.
- Verify config parsing (typo'd keys silently keep defaults) with a config dump after changes.
When it happens
Trigger: Any copilot API/GQL call on a fresh self-hosted install (default is enabled: false); admin disabled the plugin via config; environment-specific config file missing the copilot section after migration; calling copilot endpoints from tooling before enabling the plugin.
Common situations: New self-hosted deployments where AI features are opt-in; CI suites exercising copilot endpoints without enabling the flag; config typos like copilot.enable that silently leave the default false.
Related errors
- action_forbidden
- unsplash_is_not_configured
- Session not found
- AUTHENTICATION_REQUIRED
- copilot_embedding_unavailable
AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18).
Data as JSON: /api/errors/903df36f1b29dc8a.
Report an issue: GitHub.