HeyPuter/puter · error · HttpError

dest_is_not_a_directory

dest_is_not_a_directory

Error message

Target is not a directory

What it means

Thrown by LegacyFSController (readdir/list-type flow) after resolveV1Selector resolves the target entry and parent.isDir is false. The endpoint is meant to list directory contents, so a file target is rejected with legacyCode 'dest_is_not_a_directory'.

Source

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

                    }),
                ),
            );
            if (paginated) {
                res.json({
                    items: shaped,
                    ...(body.includeTotal === true
                        ? { total: shaped.length }
                        : {}),
                });
                return;
            }
            res.json(shaped);
            return;
        }

        const parent = await resolveV1Selector(this.stores.fsEntry, body);
        if (!parent.isDir) {
            throw new HttpError(400, 'Target is not a directory', {
                legacyCode: 'dest_is_not_a_directory',
            });
        }
        await assertAccess(
            this.services.acl,
            this.services.fs,
            actor,
            parent.path,
            'list',
        );

        const sortBy = this.#parseSortBy(body);
        const sortOrder = this.#parseSortOrder(body);
        const limit =
            typeof body.limit === 'number' || typeof body.limit === 'string'
                ? Number(body.limit)
                : undefined;
        const offset =

View on GitHub (pinned to 908ec23eda)

Solutions

  1. Resolve the target client-side (stat) and verify it is a directory before calling readdir.
  2. If listing siblings, derive the parent directory path with posix.dirname before calling.
  3. Confirm the uid/path you pass corresponds to a folder entry.

Example fix

// before
readdir({ path: '/docs/readme.md' }); // file, not a dir

// after
readdir({ path: '/docs' });
Defensive patterns

Strategy: type-guard

Validate before calling

const target = await stat(selector);
if (!target.is_dir) throw new Error('Target is not a directory; use readdir on a folder');

Type guard

function isDirectoryEntry(e) { return !!e && !!e.is_dir; }

Try / catch

null

Prevention

When it happens

Trigger: Calling readdir with a path or uid that points to a regular file rather than a directory; passing a file uid where a folder uid was expected.

Common situations: User selecting a file in a 'browse folder' dialog; a stored uid referencing a file that the UI assumes is a folder; a path computed by joining a filename instead of a folder.

Related errors


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