HeyPuter/puter · critical · HttpError

unauthorized

unauthorized

Error message

Authentication required

What it means

Thrown by `#requireActor` when the ALS `Context` has no `actor` set — i.e. the request reached the driver without a resolved, authenticated actor. This is a precondition guard called at the start of every mutating app operation. Returns HTTP 401 with legacyCode `unauthorized`.

Source

Thrown at src/backend/drivers/apps/AppDriver.js:767

                // Malformed config value — nothing to reserve from it.
            }
        }

        if (reserved.has(hostname)) {
            throw new HttpError(
                400,
                '`index_url` cannot point at a Puter system host',
                { legacyCode: 'bad_request' },
            );
        }
    }

    // -- Permission checks --------------------------------------------

    #requireActor() {
        const actor = Context.get('actor');
        if (!actor)
            throw new HttpError(401, 'Authentication required', {
                legacyCode: 'unauthorized',
            });
        return actor;
    }

    #requireUserOrAppActor(actor) {
        if (!actor.user)
            throw new HttpError(403, 'User actor required', {
                legacyCode: 'forbidden',
            });
    }

    async #resolve({ uid, id }) {
        if (uid) return this.#getByUidWithAlias(uid);
        if (id?.uid) return this.#getByUidWithAlias(id.uid);
        if (id?.name) return this.appStore.getByName(id.name);
        if (id?.id) return this.appStore.getById(id.id);
        if (typeof id === 'number') return this.appStore.getById(id);

View on GitHub (pinned to 908ec23eda)

Solutions

  1. Ensure the calling route carries the auth gate (`RouteOptions` auth) so actor context is populated.
  2. In background/internal callers, set the actor in Context before invoking the driver.
  3. Authenticate the request (send a valid token) before retrying.

Example fix

// before
router.post('/apps/update', (req, res) => driver.update({...req.body}));

// after
router.post('/apps/update', { auth: true }, (req, res) => driver.update({...req.body}));
Defensive patterns

Strategy: validation

Validate before calling

// This is an auth-context precondition; validate the request is authenticated
if (!req.user && !req.session) return res.status(401).send('auth required');
// and ensure the route has the auth gate so Context.actor is set

Try / catch

try {
  await driver.update({ uid, object });
} catch (e) {
  if (e.code === 'unauthorized') { /* redirect to login */ return; }
  throw e;
}

Prevention

When it happens

Trigger: Calling an app driver method (create/update/delete/upsert) in a code path where `Context.get('actor')` is unset: an unauthenticated request, a background job that forgot to set actor context, or a misconfigured route missing the auth gate.

Common situations: A controller/route missing the `auth` RouteOption so the request is anonymous by the time it hits the driver; an extension calling the driver directly without establishing actor context; tests that bypass middleware.

Understand the failure class

Related errors


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