crowdsecurity/crowdsec · error
attempting to load a new schema for existing ref %s
Error message
attempting to load a new schema for existing ref %s
What it means
RequestValidator keeps one OpenAPI schema per reference name. LoadSchema refuses to register a schema under a ref that already has a loader/schema registered, to prevent silent replacement of a live validation schema. This is a configuration/load-order error, not a schema-content error.
Source
Thrown at pkg/appsec/api_validation/api_validation.go:308
}
return fmt.Errorf("unsupported security scheme type %s", input.SecurityScheme.Type)
}
if authTokenValue == "" {
return errors.New("auth token is required but not provided")
}
return nil
}
}
func (rv *RequestValidator) LoadSchema(ref string, schema string, opts *SchemaOptions) error {
if ref == "" {
return errors.New("ref cannot be empty")
}
rv.logger.Debugf("loading schema for ref %s", ref)
if _, exists := rv.loaders[ref]; exists {
return fmt.Errorf("attempting to load a new schema for existing ref %s", ref)
}
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 {View on GitHub (pinned to 909b515798)
Solutions
- Use a unique ref for each schema (rename one of the two entries).
- Create a fresh RequestValidator instance before re-loading schemas (e.g. on reload).
- Track which refs are already loaded and skip the second LoadSchema call.
- Deduplicate schema entries in the appsec configuration so the same ref is registered once.
Example fix
// before
rv.LoadSchema("myapi", schema1, opts)
rv.LoadSchema("myapi", schema2, opts) // panics: ref exists
// after
rv.LoadSchema("myapi-v1", schema1, opts)
rv.LoadSchema("myapi-v2", schema2, opts) Defensive patterns
Strategy: validation
Validate before calling
// guard before calling LoadSchema
loaded := map[string]bool{}
func loadOnce(rv *api_validation.RequestValidator, ref, schema string, opts *api_validation.SchemaOptions) error {
if loaded[ref] {
return nil // or rebuild validator first
}
if err := rv.LoadSchema(ref, schema, opts); err != nil { return err }
loaded[ref] = true
return nil
} Try / catch
if err := rv.LoadSchema(ref, schema, opts); err != nil {
if strings.Contains(err.Error(), "existing ref") {
log.Warnf("schema %q already loaded, skipping", ref)
return nil
}
return err
} Prevention
- Give each schema a unique ref/name in the appsec config
- Create a new RequestValidator for full reloads instead of reusing refs
- Deduplicate schema entries at config-parse time
When it happens
Trigger: Calling LoadSchema twice with the same ref (e.g. two appsec config entries or two loads of the same schema name), or re-calling it after an earlier successful load instead of creating a new RequestValidator.
Common situations: Duplicate schema names in the appsec YAML config; a reload/hot-reload path that calls LoadSchema again on the same validator; looped initialization where startup code runs twice.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- missing lapi client credentials
- no appsec_config provided
- missing TLS key file
- missing TLS cert file
- invalid schema name
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/7ff7ffe7b03bda26.
Report an issue: GitHub.