ory/kratos · error
could not read schema file
Error message
could not read schema file: %w
What it means
ReadSchema loads an identity JSON schema from a URI. For file:// URIs it reads the file from disk with os.ReadFile; if the OS open/read fails (missing file, permission denied, wrong path), the error is wrapped as "could not read schema file".
Solutions
- Verify the file exists at the exact absolute path (file:// + absolute path, e.g. file:///etc/kratos/identity.schema.json)
- Check read permissions for the process user
- In containers, confirm the schema is copied/mounted into the image or volume
- Check the wrapped inner error message — it names the exact OS-level cause (no such file, permission denied)
Example fix
// before
"identity_schemas": {"default": {"file://schemas/identity.schema.json"}}
// after
"identity_schemas": {"default": {"file:///etc/config/identity.schema.json"}} Defensive patterns
Strategy: validation
Validate before calling
// Go: preflight a file:// schema URI
func schemaFileReadable(raw string) error {
u, err := url.Parse(raw)
if err != nil || u.Scheme != "file" {
return fmt.Errorf("not a file URI: %s", raw)
}
path := u.Host + u.Path
fi, err := os.Stat(path)
if err != nil {
return fmt.Errorf("schema file missing: %w", err)
}
if fi.IsDir() {
return fmt.Errorf("schema path is a directory: %s", path)
}
f, err := os.Open(path)
if err != nil {
return fmt.Errorf("schema file not readable: %w", err)
}
return f.Close()
} Try / catch
schema, err := h.ReadSchema(ctx, uri)
if err != nil {
var pathErr *os.PathError
if errors.As(err, &pathErr) {
return fmt.Errorf("identity schema %s unreadable: %v — check path/permissions", uri, pathErr.Err)
}
return err
} Prevention
- Use absolute paths in file:// URIs inside containers
- Mount or COPY the schema into the container image
- Check os.Stat on the exact path in an entrypoint preflight script
- Keep schema files alongside config with matching deploy artifacts
When it happens
Trigger: Identity schema configured as file:///path/to/schema.json where the file does not exist, the path is wrong (note: only the default scheme's empty path yields ""), permission bits block the process, or the path is a directory.
Common situations: Relative path resolved against a different working directory in containers; config pointing at the dev machine path inside Docker; file deleted after mount; read-only filesystem or missing volume mount.
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
- could not decode schema file
- could not create request
- no credentials found
- failed to unmarshal webhook configuration for
- failed to unmarshal notify_previous_addresses configuration…
AI-assisted analysis of ory/kratos@b86338da04 (2026-09-07).
Data as JSON: /api/errors/b9aa679b8eddc2d1.
Report an issue: GitHub.
Appendix: source
Thrown at schema/handler.go:236
ss[i] = identitySchemaContainer{
ID: schema.ID,
Schema: raw,
}
}
x.PaginationHeader(w, *r.URL, int64(total), page, itemsPerPage)
h.r.Writer().Write(w, r, ss)
}
func (h *Handler) ReadSchema(ctx context.Context, uri *url.URL) (data []byte, err error) {
ctx, span := h.r.Tracer(ctx).Tracer().Start(ctx, "schema.Handler.ReadSchema")
defer otelx.End(span, &err)
switch uri.Scheme {
case "file":
data, err = os.ReadFile(uri.Host + uri.Path) //nolint:gosec
if err != nil {
return nil, errors.WithStack(fmt.Errorf("could not read schema file: %w", err))
}
case "base64":
data, err = base64.StdEncoding.DecodeString(strings.TrimPrefix(uri.String(), "base64://"))
if err != nil {
return nil, errors.WithStack(fmt.Errorf("could not decode schema file: %w", err))
}
default:
req, err := retryablehttp.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil)
if err != nil {
return nil, errors.WithStack(fmt.Errorf("could not create request: %w", err))
}
resp, err := h.r.HTTPClient(ctx).Do(req)
if err != nil {
return nil, errors.WithStack(herodot.ErrUpstreamError().WithReason("could not fetch schema").WithError(err.Error()).WithDetail("uri", uri))
}
defer func() { _ = resp.Body.Close() }()
if resp.StatusCode != http.StatusOK {
if resp.StatusCode == http.StatusNotFound {View on GitHub (pinned to b86338da04)