HeyPuter/puter · error · HttpError

access_denied

access_denied

Error message

Access denied

What it means

Thrown by FSController.#assertAccess when the ACL check denies access and `acl.getSafeAclError` reports a 404 status. The 404 path means the actor is treated as unable to even *see* the resource — the system declines to confirm the entry exists to that actor. This is the standard 'deny hides existence' behavior layered on top of ACL evaluation.

Source

Thrown at src/backend/controllers/fs/FSController.ts:1747

            descriptor,
            mode,
        )) as {
            status?: unknown;
            message?: unknown;
            fields?: { code?: unknown };
        };
        const status = Number(safe?.status);
        const message =
            typeof safe?.message === 'string' && safe.message.length > 0
                ? safe.message
                : 'Access denied';
        const code =
            typeof safe?.fields?.code === 'string'
                ? safe.fields.code
                : undefined;
        const legacyCode = code === 'forbidden' ? 'access_denied' : code;
        if (status === 404) {
            throw new HttpError(404, message, {
                ...(legacyCode ? { legacyCode } : {}),
            });
        }
        throw new HttpError(403, message, {
            legacyCode: legacyCode ?? 'access_denied',
        });
    }

    #toNumberOrUndefined(value: unknown): number | undefined {
        if (typeof value === 'number' && Number.isFinite(value)) return value;
        if (typeof value === 'string' && value.trim().length > 0) {
            const parsed = Number(value);
            if (Number.isFinite(parsed)) return parsed;
        }
        return undefined;
    }

    // Accepts loose inputs from route bodies. `source`/`destination` fields may

View on GitHub (pinned to 908ec23eda)

Solutions

  1. Confirm the path is shared with or owned by the actor before issuing the call.
  2. Re-issue with an explicit uid of an entry the actor can see, or request access from the owner.
  3. Treat the 404 as authoritative in the client — do not assume a later retry will succeed without a permission change.
  4. Audit ACLService rules / shares for the path if access was expected.
Defensive patterns

Strategy: try-catch

Try / catch

try { await op(); }
catch (e) {
  if (e?.status === 404 && /denied|access/i.test(e.message)) {
    // entry not visible to actor; do not disclose existence to end user
  } else throw e;
}

Prevention

When it happens

Trigger: Calling an FS read/write operation on a path the actor has no `see`/`list` permission on, where the ACL service returns a not-found-style safe error. Common with private folders under another user's home, or paths inside an app's AppData owned by a different app uid.

Common situations: App attempting to read outside its AppData scope; user navigating to a path they can't see; deleted-from-share target; an ACL cache that hasn't propagated a newly-granted permission.

Understand the failure class

Related errors


AI-assisted analysis of HeyPuter/puter@908ec23eda (2026-08-12). Data as JSON: /api/errors/b0be6f53ca4cc79e. Report an issue: GitHub.