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

  1. Verify the path in --query.ui-config exists and is readable from the jaeger-query process.
  2. Fix the wrapped OS error's cause: correct the path or fix file permissions (chmod/chown).
  3. If you don't need a UI config, remove the --query.ui-config flag entirely (empty value returns nil config).
  4. 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

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


AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01). Data as JSON: /api/errors/5af5c8574e93c816. Report an issue: GitHub.