HeyPuter/puter · error · HttpError

subject_does_not_exist

subject_does_not_exist

Error message

entity_not_found: app:${targetAppUid}

What it means

Thrown by KVStoreDriver's cross-app access path (#assertCrossAppKvAccess) when an app attempts to operate on another app's KV namespace (optConfig.appUuid differs from the actor's own app uid) but no app exists with the requested uid. The driver resolves the target via stores.app.getByUid and fails closed with 404 when nothing comes back. Legacy code subject_does_not_exist preserves the pre-v2 error shape callers matched on.

Source

Thrown at src/backend/drivers/kv/KVStoreDriver.ts:214

        actor: Actor,
        targetAppUid: string,
        method: string,
        args: KvCallArgs,
    ): Promise<void> {
        // `null` = no scope reaches it (`flush` is namespace-wide, not an
        // entry op); `undefined` = unmapped method. Both fail closed.
        const op = APP_DATA_KV_METHOD_OPS[method];
        if (!op) {
            throw new HttpError(
                403,
                `kv: \`${method}\` is not available on another app's data`,
                { legacyCode: 'forbidden' },
            );
        }

        const target = await this.stores.app.getByUid(targetAppUid);
        if (!target) {
            throw new HttpError(404, `entity_not_found: app:${targetAppUid}`, {
                legacyCode: 'subject_does_not_exist',
            });
        }
        if (!appDataSharingAllowed(target)) {
            throw new HttpError(
                403,
                'kv: this app does not share its data with other apps',
                { legacyCode: 'forbidden' },
            );
        }

        if (
            !(await this.services.permission.check(
                actor,
                appDataPermission(targetAppUid, 'kv', op),
            ))
        ) {
            throw new HttpError(403, 'Permission denied', {

View on GitHub (pinned to 908ec23eda)

Solutions

  1. Confirm you are passing the target app's uid (not its numeric id or name) in optConfig.appUuid.
  2. Look up the target app fresh via the apps API before the kv call and use the returned uid.
  3. If the target app was deleted, switch to a live app or omit appUuid to operate on your own namespace.
  4. Regenerate and re-cache the target app uid rather than hardcoding it.

Example fix

// before
await kv.get({ key:'pref', optConfig:{ appUuid: cachedTargetUid } });

// after
const target = await apps.get(targetAppId);
if (!target?.uid) throw new Error('target app unavailable');
await kv.get({ key:'pref', optConfig:{ appUuid: target.uid } });
Defensive patterns

Strategy: validation

Validate before calling

// Resolve and verify the target app before any cross-app kv call.
if (optConfig?.appUuid) {
  const target = await apps.getByUid(optConfig.appUuid);
  if (!target) {
    throw new Error(`target app ${optConfig.appUuid} does not exist`);
  }
}
await kv.get({ key, optConfig });

Type guard

// App uid is an opaque string; only structural checks are meaningful.
const isAppUid = (v: unknown): v is string =>
  typeof v === 'string' && v.startsWith('app-') && v.length > 4;

Try / catch

try {
  await kv.get({ key, optConfig: { appUuid: targetUid } });
} catch (e) {
  if (e.status === 404 && e.code === 'subject_does_not_exist') {
    // target app is gone — refresh uid cache or fall back to own namespace
  } else throw e;
}

Prevention

When it happens

Trigger: Calling any kv method (get/set/incr/list/etc.) with optConfig.appUuid set to a uid that was never registered, was deleted, or is malformed — reached only when the caller's actor has an effectiveApp.uid and appUuid differs from it. E.g. kv.get({ key:'x', optConfig:{ appUuid:'app-deadbeef' } }) where that app uid is unknown.

Common situations: Stale app uid cached client-side after the target app was removed; copy-paste typo in the uid; passing the app's numeric id or name instead of its uid; test fixtures referencing an app that was never seeded; app uid harvested from a different environment (dev uid used against prod).

Related errors


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