crowdsecurity/crowdsec · error

failed to load schema %s: %w

Error message

failed to load schema %s: %w

What it means

LoadSchema parses the raw OpenAPI document bytes with kin-openapi's loader (LoadFromData). If the document is not parseable — invalid YAML/JSON, unreadable structure, or unresolvable $ref pointers to external files — the underlying loader error is wrapped as "failed to load schema <ref>: ...".

Source

Thrown at pkg/appsec/api_validation/api_validation.go:327

	}

	options := opts.withDefaults()
	if err := options.OnRouteNotFound.validate(); err != nil {
		return fmt.Errorf("on_route_not_found: %w", err)
	}
	if err := options.OnMethodNotAllowed.validate(); err != nil {
		return fmt.Errorf("on_method_not_allowed: %w", err)
	}
	if err := options.OnUnsupportedSecurityScheme.validate(); err != nil {
		return fmt.Errorf("on_unsupported_security_scheme: %w", err)
	}

	loader := openapi3.NewLoader()
	rv.loaders[ref] = loader

	doc, err := loader.LoadFromData([]byte(schema))
	if err != nil {
		return fmt.Errorf("failed to load schema %s: %w", ref, err)
	}

	// Is it a valid OpenAPI schema?
	// TODO: look into opts, should we expose some of them to the user ?
	if err := doc.Validate(loader.Context, openapi3.DisableExamplesValidation()); err != nil {
		return fmt.Errorf("failed to validate schema %s: %w", ref, err)
	}

	rv.warnUnsupportedSecuritySchemes(ref, doc, options.OnUnsupportedSecurityScheme)

	router, err := legacyrouter.NewRouter(doc)
	if err != nil {
		return fmt.Errorf("failed to create router for schema ref %s: %w", ref, err)
	}

	rv.openAPISchemas[ref] = SchemaData{
		Schema:  doc,
		Router:  router,

View on GitHub (pinned to 909b515798)

Solutions

  1. Fix the YAML/JSON syntax error reported in the wrapped message.
  2. Inline external $ref references, or make the referenced files resolvable relative to the crowdsec process working directory.
  3. Validate the document with a standalone OpenAPI linter (e.g. swagger-cli validate) before loading.
  4. Check the schema file path in the appsec config points to the correct, non-empty file.

Example fix

// before (in spec)
$ref: './components.yaml#/schemas/Pet'  # file not found at runtime

// after
$ref: '#/components/schemas/Pet'
Defensive patterns

Strategy: validation

Validate before calling

// parse-check with an OpenAPI loader before handing bytes to LoadSchema
loader := openapi3.NewLoader()
if _, err := loader.LoadFromData([]byte(schema)); err != nil {
    return fmt.Errorf("spec %q not parseable: %w", ref, err)
}

Try / catch

if err := rv.LoadSchema(ref, schema, opts); err != nil {
    if strings.Contains(err.Error(), "failed to load schema") {
        log.Errorf("fix YAML/JSON or $refs in %s: %v", ref, err)
    }
    return err
}

Prevention

When it happens

Trigger: Passing malformed YAML/JSON to LoadSchema; a spec containing external $ref ("./other.yaml") that the loader cannot resolve from disk; a file read producing truncated or empty content handed to LoadSchema.

Common situations: Syntax errors after hand-editing the OpenAPI file; specs split across multiple files with relative refs whose paths don't resolve in the crowdsec working directory; wrong file path in appsec config; schema file saved with BOM or mixed tabs.

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/3127c15140f0827d. Report an issue: GitHub.