jaegertracing/jaeger · error
cannot read UI config file %v: %w
Error message
cannot read UI config file %v: %w
What it means
loadUIConfig cannot read the UI base-config file given via --query.ui-config: os.ReadFile fails. The configured path is passed through filepath.Clean, so this is a genuine open/read failure (missing file, wrong path, permission denied). Jaeger wraps the OS error with the original path for diagnosis.
Source
Thrown at cmd/jaeger/internal/extension/jaegerquery/internal/static_handler.go:214
indexFile, err := open("/index.html")
if err != nil {
return nil, fmt.Errorf("cannot open index.html: %w", err)
}
defer indexFile.Close()
indexBytes, err := io.ReadAll(indexFile)
if err != nil {
return nil, fmt.Errorf("cannot read from index.html: %w", err)
}
return indexBytes, nil
}
func loadUIConfig(uiConfig string) (*loadedConfig, error) {
if uiConfig == "" {
return nil, nil
}
bytesConfig, err := os.ReadFile(filepath.Clean(uiConfig))
if err != nil {
return nil, fmt.Errorf("cannot read UI config file %v: %w", uiConfig, err)
}
var r []byte
ext := filepath.Ext(uiConfig)
switch strings.ToLower(ext) {
case ".json":
var c map[string]any
if err := json.Unmarshal(bytesConfig, &c); err != nil {
return nil, fmt.Errorf("cannot parse UI config file %v: %w", uiConfig, err)
}
r, _ = json.Marshal(c)
return &loadedConfig{
regexp: configPattern,
config: append([]byte("JAEGER_CONFIG = "), append(r, byte(';'))...),
}, nil
case ".js":View on GitHub (pinned to 806f444784)
Solutions
- Verify the path in --query.ui-config exists and is readable from the jaeger-query process.
- Fix the wrapped OS error's cause: correct the path or fix file permissions (chmod/chown).
- If you don't need a UI config, remove the --query.ui-config flag entirely (empty value returns nil config).
- In containers, confirm the volume/ConfigMap mount path matches the flag value.
Example fix
// before --query.ui-config=/etc/jaeger/ui-config.jsn // after --query.ui-config=/etc/jaeger/ui-config.json
Defensive patterns
Strategy: validation
Validate before calling
cfgPath := os.Getenv("QUERY_UI_CONFIG")
if cfgPath != "" {
if f, err := os.Open(cfgPath); err != nil {
panic(fmt.Sprintf("--query.ui-config unreadable: %v", err))
} else {
f.Close()
}
} Try / catch
if _, err := loadUIConfig(path); err != nil {
var pe *fs.PathError
if errors.As(err, &pe) && errors.Is(pe.Err, fs.ErrNotExist) {
log.Fatalf("UI config not found: %s", pe.Path)
}
return err
} Prevention
- Mount config files before the process starts (init containers / depends_on).
- Keep flag paths and volume mount paths in one templated variable.
- Run the binary with a config-existence preflight check in entrypoint scripts.
When it happens
Trigger: newStaticAssetsHandler -> loadUIConfig with a non-empty uiConfig string where os.ReadFile(filepath.Clean(uiConfig)) returns an error, e.g. file absent, typo'd path, or unreadable permissions.
Common situations: Deployment mounts the config at a different path than the flag says; Kubernetes ConfigMap not mounted; typo like ui-config=/etc/jaeger/uiconfig.json when the file is ui_config.json; running the binary as a user without read permission.
Understand the failure class
Background: "Config file not found": what it means and how to fix it in docker-sync, Maven, Vagrant, Turborepo and other tools — this error's family across 60 libraries.
Related errors
- cannot read from index.html: %w
- cannot parse UI config file %v: %w
- UI config file must define function UIConfig(): %v
- unrecognized UI config file format, expecting .js or .json f
- no sampling strategy provider specified, expecting 'adaptive
AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01).
Data as JSON: /api/errors/5af5c8574e93c816.
Report an issue: GitHub.