agalwood/Motrix · error · FsSandboxError

plugin.fs.path_too_long

plugin.fs.path_too_long

Error message

plugin.fs.path_too_long: path exceeds ${PATH_MAX} characters

What it means

Thrown by `resolveInsideSandbox(root, userPath)` when `userPath.length > PATH_MAX` (4096). The sandbox resolver rejects oversized paths up front before doing any normalization or filesystem work, as a hard guard against path-traversal payloads that rely on length. Code is `plugin.fs.path_too_long`.

Source

Thrown at src/core/plugin/capabilities/fs-sandbox.ts:27

export class FsSandboxError extends Error {
  constructor(
    public readonly code: string,
    message: string
  ) {
    super(message)
    this.name = 'FsSandboxError'
  }
}

const PATH_MAX = 4096

export async function resolveInsideSandbox(
  root: string,
  userPath: string
): Promise<string> {
  if (userPath.length > PATH_MAX) {
    throw new FsSandboxError(
      'plugin.fs.path_too_long',
      `plugin.fs.path_too_long: path exceeds ${PATH_MAX} characters`
    )
  }
  const normalized = userPath.normalize('NFC')
  const absolute = path.resolve(root, normalized)
  let real: string
  try {
    real = await realpath(absolute)
  } catch (e: unknown) {
    if ((e as NodeJS.ErrnoException).code === 'ENOENT') {
      real = path.normalize(
        path.join(
          await realpath(path.dirname(absolute)),
          path.basename(absolute)
        )
      )
    } else {

View on GitHub (pinned to 1a708ee577)

Solutions

  1. Cap relPath length at the plugin's trust boundary (e.g. reject >1024 chars well under the 4096 limit) and surface a friendlier error.
  2. Switch from a single long relPath to multiple shorter operations or use directory hierarchy.
  3. Sanitize/reject inputs that are concatenated into the path before calling the fs API.
  4. If the long path is legitimate, restructure storage so individual operations stay under the cap.

Example fix

// before
const rel = segments.join('/') // segments unbounded
await storage.read(rel) // may exceed 4096

// after
const rel = segments.join('/')
if (rel.length > 1024) {
  throw new Error(`path too long: ${rel.length} chars`)
}
await storage.read(rel)
Defensive patterns

Strategy: validation

Validate before calling

function assertRelPathLen(rel: string, max = 1024): void {
  if (typeof rel !== 'string' || rel.length > max) {
    throw new Error(`relPath too long (${rel?.length} > ${max})`)
  }
}

Type guard

function isPathTooLong(e: unknown): boolean {
  return e instanceof Error && (e as FsSandboxError).code === 'plugin.fs.path_too_long'
}

Try / catch

try {
  await storage.read(rel)
} catch (e) {
  if (isPathTooLong(e)) { /* reject caller's input */ }
  else throw e
}

Prevention

When it happens

Trigger: Calling any fs-storage operation (stat/read/write/delete) whose relPath, after concatenation by the caller, exceeds 4096 characters; or a plugin directly invoking resolveInsideSandbox with a path built from unbounded user input.

Common situations: Plugin constructs a path from a long list of segments without a cap; adversarial input designed to overflow path buffers; a deeply recursive directory generator producing very long relative paths.

Related errors


AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12). Data as JSON: /api/errors/c23590b1014dcee4. Report an issue: GitHub.