toeverything/AFFiNE · warning · ActionForbidden

action_forbidden

action_forbidden

Error message

You are not allowed to perform this action.

What it means

This ActionForbidden error (HTTP 403) is thrown by the ErrorResolver's placeholder GraphQL 'error' query, which exists solely to register the ErrorDataUnionType in the GraphQL schema. The query always throws ActionForbidden — it is not a real endpoint and should never be called by clients. Hitting it means a client is querying the 'error' field directly, which is not a valid operation.

Source

Thrown at packages/backend/server/src/base/error/index.ts:16

import { writeFileSync } from 'node:fs';
import { join } from 'node:path';
import { fileURLToPath } from 'node:url';

import { Logger, Module, OnModuleInit } from '@nestjs/common';
import { Args, Query, Resolver } from '@nestjs/graphql';

import { generateUserFriendlyErrors } from './def';
import { ActionForbidden, ErrorDataUnionType, ErrorNames } from './errors.gen';

@Resolver(() => ErrorDataUnionType)
class ErrorResolver {
  // only exists for type registering
  @Query(() => ErrorDataUnionType)
  error(@Args({ name: 'name', type: () => ErrorNames }) _name: ErrorNames) {
    throw new ActionForbidden();
  }
}

@Module({
  providers: [ErrorResolver],
})
export class ErrorModule implements OnModuleInit {
  logger = new Logger('ErrorModule');
  onModuleInit() {
    if (!env.dev) {
      return;
    }
    this.logger.log('Generating UserFriendlyError classes');
    const def = generateUserFriendlyErrors();

    writeFileSync(
      join(fileURLToPath(import.meta.url), '../errors.gen.ts'),
      def

View on GitHub (pinned to 26c515e050)

Solutions

  1. Do not query the 'error' GraphQL field — it is a type-registration placeholder, not a real endpoint.
  2. Review client GraphQL queries and remove any references to the 'error' query field.
  3. If you see this in logs from automated tools, add the 'error' field to the tool's ignore/exclude list.

Example fix

// before (GraphQL query)
query { error(name: BAD_REQUEST) { ... } } // always throws ActionForbidden

// after
// Remove the query entirely; this field is not a real API endpoint.
Defensive patterns

Strategy: validation

Validate before calling

// Do not query the 'error' GraphQL field.
// It exists only for schema type registration.
// Before sending a query, verify the field is a real API endpoint:
const realQueries = ['user', 'workspace', 'doc'];
if (!realQueries.includes(queryName)) {
  console.warn(`'${queryName}' is not a valid query field.`);
}

Try / catch

try {
  const result = await client.query({ query: MY_QUERY });
} catch (e) {
  if (e.message?.includes('action_forbidden')) {
    // likely queried the placeholder 'error' field; review the query
  }
}

Prevention

When it happens

Trigger: A GraphQL client executing a query against the 'error' field (e.g. query { error(name: ...) { ... } }). This field exists only for schema type registration and is not a functional API. Automated GraphQL introspection tools or fuzzers that query every field may trigger it.

Common situations: GraphQL exploration tools (Apollo Studio, GraphiQL auto-complete) that query the error field during schema exploration. Misconfigured client code that references the error union type as a query. Security scanners or fuzzers probing all GraphQL endpoints.

Related errors


AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12). Data as JSON: /api/errors/ace3b2db5d35922d. Report an issue: GitHub.