HeyPuter/puter · warning · HttpError

app_index_url_already_in_use

app_index_url_already_in_use

Error message

App index_url already in use

What it means

Thrown by `#ensureIndexUrlNotAlreadyInUse` when an app row already references the given `index_url` (or its candidate variants) and isn't excluded by `excludeAppId`. Returns HTTP 400 with legacyCode `app_index_url_already_in_use`, carrying `fields.index_url` and `fields.app_uid` of the conflicting app.

Source

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

            }
        }

        if (candidates.size === 0) return null;
        const candidateList = [...candidates];
        if (hasIndexUrlUniquenessExemption(candidateList)) return null;

        return this.appStore.findByIndexUrlCandidates(candidateList, {
            excludeAppId,
        });
    }

    async #ensureIndexUrlNotAlreadyInUse({ indexUrl, excludeAppId } = {}) {
        const conflictRow = await this.#findIndexUrlConflictRow({
            indexUrl,
            excludeAppId,
        });
        if (conflictRow) {
            throw new HttpError(400, 'App index_url already in use', {
                legacyCode: 'app_index_url_already_in_use',
                fields: {
                    index_url: indexUrl,
                    app_uid: conflictRow.uid,
                },
            });
        }
    }

    async #ensurePuterSiteSubdomainIsOwned(indexUrl, user) {
        if (!user) return;
        const subdomain = this.#extractPuterHostedSubdomain(indexUrl);
        if (!subdomain) return;

        let row = await this.stores.subdomain.getBySubdomain(subdomain);
        if (!row) {
            // Deploys create the subdomain and immediately point the app
            // at it, so a replica or peer-cache miss here would wrongly

View on GitHub (pinned to 908ec23eda)

Solutions

  1. Point the app at a unique origin/index_url.
  2. Update or delete the existing app that holds the conflicting index_url first.
  3. If reassigning within the same app, the update path passes `excludeAppId` so self-conflicts are allowed.

Example fix

// before
driver.create({ object: { name:'a', index_url:'https://x.com/i.html' } });
// another create with same index_url -> 400

// after
await driver.update({ uid: existingApp, object: { index_url:'https://x.com/i.html' } });
// or delete the holder first
Defensive patterns

Strategy: validation

Validate before calling

// Resolve candidates like the driver does and check before create
const conflicts = await appStore.findByIndexUrlCandidates([indexUrl], {});
if (conflicts.length) throw new Error('index_url already in use');
await driver.create({ object: { index_url } });

Try / catch

try {
  await driver.create({ object });
} catch (e) {
  if (e.code === 'app_index_url_already_in_use') { object.index_url = uniqueOrigin(); await driver.create({object}); return; }
  throw e;
}

Prevention

When it happens

Trigger: Creating/updating an app with an `index_url` that another app already uses, during the non-merge path (`update` with an `excludeAppId` for the current app). `#findIndexUrlConflictRow` resolves origin variants, so scheme/port variants of the same origin also collide.

Common situations: Two apps pointed at the same deployed origin; redeploying to an index_url an abandoned app still holds; CDN/origin reuse across app entries.

Related errors


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