hasura/graphql-engine · critical
could not read metadata
Error message
could not read metadata
What it means
Panic from expect() in the engine's main() when the metadata (OpenDD) JSON file cannot be read from disk. The engine requires the metadata document describing connectors and authentication to start, so an unreadable file aborts startup.
Source
Thrown at v3/crates/engine/bin/engine/main.rs:147
tracing_util::shutdown_tracer();
}
#[allow(clippy::print_stdout)]
async fn start_engine(server: &ServerOptions) -> Result<(), StartupError> {
let metadata_resolve_configuration = metadata_resolve::configuration::Configuration {
unstable_features: resolve_unstable_features(&server.unstable_features),
};
let expose_internal_errors = if server.expose_internal_errors {
ExposeInternalErrors::Expose
} else {
ExposeInternalErrors::Censor
};
let raw_auth_config =
std::fs::read_to_string(&server.authn_config_path).expect("could not read auth config");
let opendd_metadata_json =
std::fs::read_to_string(&server.metadata_path).expect("could not read metadata");
let (resolved_metadata, auth_config) = engine::resolve_metadata(
&opendd_metadata_json,
&raw_auth_config,
&metadata_resolve_configuration,
)
.map_err(StartupError::ReadSchema)?;
let state = engine::build_state(
expose_internal_errors,
auth_config,
resolved_metadata,
server.auth_mode_header.clone(),
server.ndc_response_size_limit,
)
.map_err(StartupError::ReadSchema)?;
let mut app = get_base_routes(state.clone(), server.request_body_limit);View on GitHub (pinned to 724551b9ae)
Solutions
- Confirm the metadata file exists at the exact path passed to the binary
- Regenerate metadata via your build/federation step if it was never produced
- Ensure the file is valid UTF-8 text (file <path>, iconv if needed)
- Fix permissions or mount the file into the container
Example fix
// before
let opendd_metadata_json =
std::fs::read_to_string(&server.metadata_path).expect("could not read metadata");
// after
let opendd_metadata_json = std::fs::read_to_string(&server.metadata_path)
.with_context(|| format!("could not read metadata at {}", server.metadata_path.display()))?; Defensive patterns
Strategy: validation
Validate before calling
let p = &server.metadata_path;
assert!(p.is_file(), "metadata file missing: {}", p.display());
let bytes = std::fs::read(p)?;
let opendd_metadata_json = String::from_utf8(bytes)?; Try / catch
Convert the expect() into a Result with context (path + io error kind) so startup surfaces an actionable message.
Prevention
- Generate metadata as a build artifact and validate in CI
- Fail fast in Dockerfiles if the metadata file is absent
- Keep metadata generation and engine startup in the same pipeline
When it happens
Trigger: Starting the engine with a metadata path that does not exist, is unreadable, is a directory, or contains non-UTF8 bytes (read_to_string requires valid UTF-8).
Common situations: Metadata file not generated or not copied into CI/deployment artifacts, path typos in launch scripts, non-UTF8 metadata produced by other tooling, or missing volume mounts.
Related errors
- could not read auth config
- failed to build engine state - {0}
- writing metadata to file: %w
- reading metadata file: %w
- reading local metadata: %w
AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28).
Data as JSON: /api/errors/c6302b0616d2611c.
Report an issue: GitHub.