HeyPuter/puter · critical · HttpError

internal_error

internal_error

Error message

Owner not found

What it means

Thrown by POST /writeFile when the target entry exists but its owning user record could not be loaded from the user store. This is a 500 internal_error — a data-integrity problem: an FS entry references a userId that has no corresponding user row. It is not a client mistake; it indicates a corrupt or partially-migrated database.

Source

Thrown at src/backend/controllers/fs/LegacyFSController.ts:1404

                signature: query.signature as string,
            },
            'write',
            signingCfg,
        );

        const uid = typeof query.uid === 'string' ? query.uid : '';
        const targetEntry = await resolveV1Selector(this.stores.fsEntry, {
            uid,
        });
        if (!targetEntry)
            throw new HttpError(404, 'Item not found', {
                legacyCode: 'not_found',
            });

        // Owner suspension check.
        const owner = await this.stores.user.getById(targetEntry.userId);
        if (!owner)
            throw new HttpError(500, 'Owner not found', {
                legacyCode: 'internal_error',
            });
        if ((owner as { suspended?: unknown }).suspended)
            throw new HttpError(401, 'Account suspended', {
                legacyCode: 'account_suspended',
            });

        const userId = targetEntry.userId;
        const operation =
            typeof query.operation === 'string' ? query.operation : 'write';

        // A valid write signature authorises overwriting the file's bytes,
        // not structural changes. Restrict copy/move/mkdir/rename/delete/trash
        // to a caller authenticated as the owner — otherwise a recipient of a
        // write-share could relocate or destroy the source via this endpoint.
        if (operation !== 'write' && req.actor?.user?.id !== userId) {
            throw new HttpError(
                403,

View on GitHub (pinned to 908ec23eda)

Solutions

  1. Report to an operator/maintainer — this is a server-side data integrity bug, not fixable from the client.
  2. As an operator, reconcile the orphaned entry: reassign or purge entries whose userId has no user row.
  3. Re-sign against a different, owned entry as a workaround.
Defensive patterns

Strategy: fallback

Try / catch

try { await fetch(writeUrl, { method:'POST', body: form }); }
catch (e) {
  if (e.code === 'internal_error' && /Owner not found/i.test(e.message)) {
    // not client-fixable; report and pick an alternate target
  } else throw e;
}

Prevention

When it happens

Trigger: POST /writeFile against an entry whose userId points to a deleted/orphaned user row; a migration that created entries without users; foreign-key gap in the store.

Common situations: Post-migration orphaned entries; a user hard-deleted while their files remained; test fixtures with synthetic userIds.

Related errors


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