crowdsecurity/crowdsec · error
unable to read schema file %s : %w
Error message
unable to read schema file %s : %w
What it means
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.
Source
Thrown at pkg/appsec/appsec.go:1885
if bouncerStatusCode == 0 {
bouncerStatusCode = w.Config.BouncerBlockedHTTPCode
}
}
return bouncerStatusCode, resp
}
const schemasSubDir = "schemas"
func (w *AppsecRuntimeConfig) loadAPISchema(ref, filename string, opts *apivalidation.SchemaOptions) error {
if !filepath.IsLocal(filename) {
return fmt.Errorf("schema filename %q must be relative to %s and stay within it", filename, schemasSubDir)
}
schemaPath := filepath.Join(w.DataDir, schemasSubDir, filename)
w.Logger.Debugf("loading schema %s for ref %s", schemaPath, ref)
schema, err := os.ReadFile(schemaPath)
if err != nil {
return fmt.Errorf("unable to read schema file %s : %w", schemaPath, err)
}
return w.RequestValidator.LoadSchema(ref, string(schema), opts)
}
func (w *AppsecRuntimeConfig) LoadAPISchemaWithName(ref string, filename string) error {
return w.loadAPISchema(ref, filename, nil)
}
// LoadAPISchemaWithOptions behaves like LoadAPISchemaWithName but accepts a
// map of policy overrides. Supported keys:
// - "on_route_not_found": "drop" | "ignore" (default: "drop")
// - "on_method_not_allowed": "drop" | "ignore" (default: "drop")
// - "on_unsupported_security_scheme": "drop" | "ignore" (default: "drop")
func (w *AppsecRuntimeConfig) LoadAPISchemaWithOptions(ref string, filename string, opts map[string]any) error {
schemaOpts, err := parseSchemaOptions(opts)
if err != nil {
return err
}View on GitHub (pinned to 909b515798)
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
Example fix
// before schema: userschema.json # file not present // after (after copying userschema.json into <data_dir>/schemas/) schema: userschema.json
Defensive patterns
Strategy: validation
Validate before calling
p := filepath.Join(dataDir, "schemas", filename)
if fi, err := os.Stat(p); err != nil || fi.IsDir() {
return fmt.Errorf("schema %s missing or invalid: %w", p, err)
} Try / catch
if err := rt.LoadAPISchema(ref, filename); err != nil {
if errors.Is(err, os.ErrNotExist) {
log.Fatalf("schema file missing — install it into %s", schemasDir)
}
if errors.Is(err, os.ErrPermission) {
log.Fatalf("fix permissions on schema file: %v", err)
}
return err
} Prevention
- 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)
When it happens
Trigger: os.ReadFile failing on the joined schemaPath: filename typo, schema never copied into the schemas dir, wrong data_dir setting, or read permissions.
Common situations: 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.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- invalid schema name
- appsec datasource requires a hub. this is a bug, please repo
- appsec datasource requires a lapi client configuration. this
- missing lapi client credentials
- no appsec_config provided
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/e7b6004ba37cfe8a.
Report an issue: GitHub.