jaegertracing/jaeger · error

cannot load index.html: %w

Error message

cannot load index.html: %w

What it means

newStaticAssetsHandler builds the handler that serves the Jaeger UI. It resolves the asset filesystem (embedded UI files by default, or http.Dir(AssetsPath) when ui.assets-path is set) and then reads index.html through loadIndexHTML. If reading/parsing index.html fails for any reason, construction aborts with this wrapped error so a broken UI deployment fails at startup instead of serving a broken page.

Source

Thrown at cmd/jaeger/internal/extension/jaegerquery/internal/static_handler.go:112

}

type loadedConfig struct {
	regexp *regexp.Regexp
	config []byte
}

func newStaticAssetsHandler(
	qOpts *QueryOptions,
	backendCaps BackendCapabilityProvider,
	logger *zap.Logger,
) (*staticAssetsHandler, error) {
	assetsFS := ui.GetStaticFiles(logger)
	if qOpts.UIConfig.AssetsPath != "" {
		assetsFS = http.Dir(qOpts.UIConfig.AssetsPath)
	}
	raw, err := loadIndexHTML(assetsFS.Open)
	if err != nil {
		return nil, fmt.Errorf("cannot load index.html: %w", err)
	}
	h := &staticAssetsHandler{
		assetsFS:     assetsFS,
		basePath:     qOpts.BasePath,
		logAccess:    qOpts.UIConfig.LogAccess,
		backendCaps:  backendCaps,
		logger:       logger,
		indexHTMLRaw: raw,
		uiConfigFile: qOpts.UIConfig.ConfigFile,
	}
	if h.uiConfigFile != "" {
		// Eager initial load: surface UI-config syntax errors at startup
		// rather than letting them appear on the first page-load several
		// seconds later. Subsequent reloads are lazy, gated by uiConfigExpiry.
		cfg, err := loadUIConfig(h.uiConfigFile)
		if err != nil {
			return nil, err
		}

View on GitHub (pinned to 806f444784)

Solutions

  1. Verify the assets path: ls <assets-path>/index.html — ensure the file exists at the root of the configured directory, not in a nested subfolder
  2. If the path is wrong, correct ui.assets-path or remove it to fall back to the UI embedded in the Jaeger binary
  3. Fix filesystem permissions so the jaeger process can read index.html
  4. Re-download/rebuild the custom UI and confirm index.html is present and non-empty before restarting

Example fix

// before
query:
  ui:
    assets-path: /opt/jaeger-ui/dist/assets   # index.html not here
// after
query:
  ui:
    assets-path: /opt/jaeger-ui/dist          # directory containing index.html
Defensive patterns

Strategy: validation

Validate before calling

// verify the assets path before constructing the server
func validateAssetsPath(dir string) error {
	if dir == "" {
		return nil // embedded UI is used
	}
	fi, err := os.Stat(filepath.Join(dir, "index.html"))
	if err != nil {
		return fmt.Errorf("assets path %q has no index.html: %w", dir, err)
	}
	if fi.IsDir() || fi.Size() == 0 {
		return fmt.Errorf("%q/index.html is a directory or empty", dir)
	}
	return nil
}

Try / catch

handler, err := newStaticAssetsHandler(qOpts, caps, logger)
if err != nil {
	var pathErr *fs.PathError
	if errors.As(err, &pathErr) {
		log.Fatalf("UI assets broken at %s: %v", pathErr.Path, err)
	}
	return err
}

Prevention

When it happens

Trigger: Calling RegisterStaticHandler/newStaticAssetsHandler when loadIndexHTML fails: the configured ui.assets-path directory does not exist or contains no index.html, the file is unreadable (permissions), or it is empty/corrupt so the load step rejects it.

Common situations: Pointing --query.ui-config assets-path at a directory where the Jaeger UI zip was not fully extracted; a Docker volume mounted empty or at the wrong path; permission changes after a container restart; a custom UI build that forgot to emit index.html at the root of the assets directory.

Related errors


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