{"record":{"id":"e7b6004ba37cfe8a","repo":"crowdsecurity/crowdsec","slug":"unable-to-read-schema-file-s-w","errorCode":null,"errorMessage":"unable to read schema file %s : %w","messagePattern":"unable to read schema file (.+?) : %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/appsec/appsec.go","lineNumber":1885,"sourceCode":"\t\tif bouncerStatusCode == 0 {\n\t\t\tbouncerStatusCode = w.Config.BouncerBlockedHTTPCode\n\t\t}\n\t}\n\n\treturn bouncerStatusCode, resp\n}\n\nconst schemasSubDir = \"schemas\"\n\nfunc (w *AppsecRuntimeConfig) loadAPISchema(ref, filename string, opts *apivalidation.SchemaOptions) error {\n\tif !filepath.IsLocal(filename) {\n\t\treturn fmt.Errorf(\"schema filename %q must be relative to %s and stay within it\", filename, schemasSubDir)\n\t}\n\tschemaPath := filepath.Join(w.DataDir, schemasSubDir, filename)\n\tw.Logger.Debugf(\"loading schema %s for ref %s\", schemaPath, ref)\n\tschema, err := os.ReadFile(schemaPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to read schema file %s : %w\", schemaPath, err)\n\t}\n\treturn w.RequestValidator.LoadSchema(ref, string(schema), opts)\n}\n\nfunc (w *AppsecRuntimeConfig) LoadAPISchemaWithName(ref string, filename string) error {\n\treturn w.loadAPISchema(ref, filename, nil)\n}\n\n// LoadAPISchemaWithOptions behaves like LoadAPISchemaWithName but accepts a\n// map of policy overrides. Supported keys:\n//   - \"on_route_not_found\":             \"drop\" | \"ignore\"  (default: \"drop\")\n//   - \"on_method_not_allowed\":          \"drop\" | \"ignore\"  (default: \"drop\")\n//   - \"on_unsupported_security_scheme\": \"drop\" | \"ignore\"  (default: \"drop\")\nfunc (w *AppsecRuntimeConfig) LoadAPISchemaWithOptions(ref string, filename string, opts map[string]any) error {\n\tschemaOpts, err := parseSchemaOptions(opts)\n\tif err != nil {\n\t\treturn err\n\t}","sourceCodeStart":1867,"sourceCodeEnd":1903,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/appsec/appsec.go#L1867-L1903","documentation":"After passing the path-safety check, loadAPISchema reads the schema file from <data_dir>/schemas/<filename> with os.ReadFile. Any read failure — missing file, permissions, is-a-directory — is wrapped as this error. The API request validator then cannot validate requests against the referenced schema.","triggerScenarios":"os.ReadFile failing on the joined schemaPath: filename typo, schema never copied into the schemas dir, wrong data_dir setting, or read permissions.","commonSituations":"Referencing a schema file that was never installed; running crowdsec in a container where the schemas dir wasn't mounted; permission denied after hardening; filename case mismatch.","solutions":["Verify the file exists at <data_dir>/schemas/<filename> (ls the directory) and fix the configured name/typos","Check file permissions so the crowdsec user can read it","Confirm the data_dir config points to the directory that actually holds schemas/","Copy or mount the schema file into the schemas directory if it's missing (e.g. in containers)","Note the wrapped error: `no such file` vs `permission denied` vs `is a directory` point to different fixes"],"exampleFix":"// before\nschema: userschema.json   # file not present\n// after (after copying userschema.json into <data_dir>/schemas/)\nschema: userschema.json","handlingStrategy":"validation","validationCode":"p := filepath.Join(dataDir, \"schemas\", filename)\nif fi, err := os.Stat(p); err != nil || fi.IsDir() {\n    return fmt.Errorf(\"schema %s missing or invalid: %w\", p, err)\n}","typeGuard":null,"tryCatchPattern":"if err := rt.LoadAPISchema(ref, filename); err != nil {\n    if errors.Is(err, os.ErrNotExist) {\n        log.Fatalf(\"schema file missing — install it into %s\", schemasDir)\n    }\n    if errors.Is(err, os.ErrPermission) {\n        log.Fatalf(\"fix permissions on schema file: %v\", err)\n    }\n    return err\n}","preventionTips":["Deploy schema files as part of the same pipeline as the config referencing them","Check existence/permissions in container entrypoints before starting crowdsec","Match filename case exactly (Linux filesystems are case-sensitive)"],"tags":["appsec","schema","file"],"backgroundTag":"file-read-failed","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}