remix-run/remix · error · AssetServerCompilationError

FILE_NOT_ALLOWED

FILE_NOT_ALLOWED

Error message

File "${identityPath}" is not allowed by the asset server access configuration. Add a matching allowFiles or allowPackages rule, or remove a conflicting denyFiles rule.

What it means

The asset server compiler resolves each requested file to an identity path and then checks it against the access configuration (`allowFiles`/`allowPackages`/`denyFiles` rules) before generating a stable URL. If `args.isAllowed(identityPath)` returns false, compilation fails with FILE_NOT_ALLOWED — this is an explicit access-control rejection, not a missing file.

Source

Thrown at packages/assets/src/lib/files/compiler.ts:561

  let identityPath = resolveExistingFilePath(filePath)
  if (!identityPath) {
    throw createAssetServerCompilationError(`File not found: ${filePath}`, {
      code: 'FILE_NOT_FOUND',
    })
  }

  if (!isServedFilePath(identityPath, args.extensions)) {
    throw createAssetServerCompilationError(`File type is not supported: ${identityPath}`, {
      code: 'FILE_NOT_SUPPORTED',
    })
  }

  if (!args.isAllowed(identityPath)) {
    throw createAssetServerCompilationError(
      `File "${identityPath}" is not allowed by the asset server access configuration. ` +
        `Add a matching allowFiles or allowPackages rule, or remove a conflicting denyFiles rule.`,
      {
        code: 'FILE_NOT_ALLOWED',
      },
    )
  }

  let stableUrlPathname = args.routes.toUrlPathname(identityPath)
  if (!stableUrlPathname) {
    throw createAssetServerCompilationError(
      `File ${identityPath} is outside all configured mounts.`,
      {
        code: 'FILE_OUTSIDE_MOUNTS',
      },
    )
  }

  return {
    identityPath,
    stableUrlPathname,
  }

View on GitHub (pinned to 9696913134)

Solutions

  1. Add an allowFiles glob or allowPackages rule matching the file's identity path
  2. Check for a conflicting denyFiles rule that matches the path and remove/narrow it
  3. Verify the identity path spelling (relative form, extension) against your rule globs — mismatches silently fail the allow check

Example fix

// before
files({ allowFiles: ['app/assets/**'], denyFiles: ['**/*.secret'] })

// after
files({ allowFiles: ['app/assets/**', 'app/private-assets/logo.svg'], denyFiles: ['**/*.secret'] })
Defensive patterns

Strategy: validation

Validate before calling

// Mirror the compiler's check before building:
const identityPath = toIdentityPath(filePath)
if (!isAllowedByConfig(identityPath, { allowFiles, allowPackages, denyFiles })) {
  // add rule or exclude the file from the build instead of failing later
}

Type guard

function isAllowedByConfig(path: string, cfg: AccessConfig): boolean {
  if (cfg.denyFiles.some((g) => match(g, path))) return false
  return cfg.allowFiles.some((g) => match(g, path)) || cfg.allowPackages.some((p) => path.startsWith(p))
}

Try / catch

try {
  const resolved = compiler.resolvedFile(file)
} catch (error) {
  if (error?.code === 'FILE_NOT_ALLOWED') {
    // surface a config-specific message listing matching deny rules
  }
  throw error
}

Prevention

When it happens

Trigger: Requesting/serving a file whose identity path matches no `allowFiles`/`allowPackages` rule, or matches a `denyFiles` rule, in the asset server configuration. Triggered when the compiler resolves a served file (via `resolvedFile`) for a route/import that references the file.

Common situations: Adding new source files outside the allowed directories (e.g. importing from a package or path not covered by allowPackages); a security-hardened config that denies dotfiles/node_modules and a new import hits the deny rule; misconfigured globs in allowFiles that don't match the actual case or extension of the file.

Related errors


AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27). Data as JSON: /api/errors/ba558f08c9840e80. Report an issue: GitHub.