{"record":{"id":"ba558f08c9840e80","repo":"remix-run/remix","slug":"file-not-allowed","errorCode":"FILE_NOT_ALLOWED","errorMessage":"File \"${identityPath}\" is not allowed by the asset server access configuration. Add a matching allowFiles or allowPackages rule, or remove a conflicting denyFiles rule.","messagePattern":"File \"(.+?)\" is not allowed by the asset server access configuration\\. Add a matching allowFiles or allowPackages rule, or remove a conflicting denyFiles rule\\.","errorType":"error_code","errorClass":"AssetServerCompilationError","httpStatus":null,"severity":"error","filePath":"packages/assets/src/lib/files/compiler.ts","lineNumber":561,"sourceCode":"  let identityPath = resolveExistingFilePath(filePath)\n  if (!identityPath) {\n    throw createAssetServerCompilationError(`File not found: ${filePath}`, {\n      code: 'FILE_NOT_FOUND',\n    })\n  }\n\n  if (!isServedFilePath(identityPath, args.extensions)) {\n    throw createAssetServerCompilationError(`File type is not supported: ${identityPath}`, {\n      code: 'FILE_NOT_SUPPORTED',\n    })\n  }\n\n  if (!args.isAllowed(identityPath)) {\n    throw createAssetServerCompilationError(\n      `File \"${identityPath}\" is not allowed by the asset server access configuration. ` +\n        `Add a matching allowFiles or allowPackages rule, or remove a conflicting denyFiles rule.`,\n      {\n        code: 'FILE_NOT_ALLOWED',\n      },\n    )\n  }\n\n  let stableUrlPathname = args.routes.toUrlPathname(identityPath)\n  if (!stableUrlPathname) {\n    throw createAssetServerCompilationError(\n      `File ${identityPath} is outside all configured mounts.`,\n      {\n        code: 'FILE_OUTSIDE_MOUNTS',\n      },\n    )\n  }\n\n  return {\n    identityPath,\n    stableUrlPathname,\n  }","sourceCodeStart":543,"sourceCodeEnd":579,"githubUrl":"https://github.com/remix-run/remix/blob/9696913134be3a4423513d2775f7b31d6917c049/packages/assets/src/lib/files/compiler.ts#L543-L579","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Add an allowFiles glob or allowPackages rule matching the file's identity path","Check for a conflicting denyFiles rule that matches the path and remove/narrow it","Verify the identity path spelling (relative form, extension) against your rule globs — mismatches silently fail the allow check"],"exampleFix":"// before\nfiles({ allowFiles: ['app/assets/**'], denyFiles: ['**/*.secret'] })\n\n// after\nfiles({ allowFiles: ['app/assets/**', 'app/private-assets/logo.svg'], denyFiles: ['**/*.secret'] })","handlingStrategy":"validation","validationCode":"// Mirror the compiler's check before building:\nconst identityPath = toIdentityPath(filePath)\nif (!isAllowedByConfig(identityPath, { allowFiles, allowPackages, denyFiles })) {\n  // add rule or exclude the file from the build instead of failing later\n}","typeGuard":"function isAllowedByConfig(path: string, cfg: AccessConfig): boolean {\n  if (cfg.denyFiles.some((g) => match(g, path))) return false\n  return cfg.allowFiles.some((g) => match(g, path)) || cfg.allowPackages.some((p) => path.startsWith(p))\n}","tryCatchPattern":"try {\n  const resolved = compiler.resolvedFile(file)\n} catch (error) {\n  if (error?.code === 'FILE_NOT_ALLOWED') {\n    // surface a config-specific message listing matching deny rules\n  }\n  throw error\n}","preventionTips":["Keep allow/deny globs in one reviewed config file","Add a CI test that every servable directory matches at least one allow rule and no deny rule"],"tags":["asset-server","access-control","configuration","files"],"backgroundTag":"file-access-denied-by-config","analyzedSha":"9696913134be3a4423513d2775f7b31d6917c049","analyzedAt":"2026-08-27T19:55:01.024Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}