{"record":{"id":"2d7701f2487a0e5d","repo":"jaegertracing/jaeger","slug":"ui-config-file-must-define-function-uiconfig-v","errorCode":null,"errorMessage":"UI config file must define function UIConfig(): %v","messagePattern":"UI config file must define function UIConfig\\(\\): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/jaeger/internal/extension/jaegerquery/internal/static_handler.go","lineNumber":236,"sourceCode":"\text := filepath.Ext(uiConfig)\n\tswitch strings.ToLower(ext) {\n\tcase \".json\":\n\t\tvar c map[string]any\n\n\t\tif err := json.Unmarshal(bytesConfig, &c); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"cannot parse UI config file %v: %w\", uiConfig, err)\n\t\t}\n\t\tr, _ = json.Marshal(c)\n\n\t\treturn &loadedConfig{\n\t\t\tregexp: configPattern,\n\t\t\tconfig: append([]byte(\"JAEGER_CONFIG = \"), append(r, byte(';'))...),\n\t\t}, nil\n\tcase \".js\":\n\t\tr = bytes.TrimSpace(bytesConfig)\n\t\tre := regexp.MustCompile(`function\\s+UIConfig(\\s)?\\(\\s?\\)(\\s)?{`)\n\t\tif !re.Match(r) {\n\t\t\treturn nil, fmt.Errorf(\"UI config file must define function UIConfig(): %v\", uiConfig)\n\t\t}\n\n\t\treturn &loadedConfig{\n\t\t\tregexp: configJsPattern,\n\t\t\tconfig: r,\n\t\t}, nil\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unrecognized UI config file format, expecting .js or .json file: %v\", uiConfig)\n\t}\n}\n\nfunc (h *staticAssetsHandler) loggingHandler(handler http.Handler) http.Handler {\n\tif !h.logAccess {\n\t\treturn handler\n\t}\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\th.logger.Info(\"serving static asset\", zap.Stringer(\"url\", r.URL))\n\t\thandler.ServeHTTP(w, r)","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/cmd/jaeger/internal/extension/jaegerquery/internal/static_handler.go#L218-L254","documentation":"A UI config file with a .js extension must define a JavaScript function named UIConfig(), verified by regex `function\\s+UIConfig(\\s)?\\(\\s?\\)(\\s)?{`. If the trimmed file content does not match, loadUIConfig rejects it because the handler cannot inject a config the UI can call. Note this rejects arrow functions and minified forms like function UIConfig(){...} only if the regex fails (it actually matches that), but rejects `const UIConfig = () => ({...})`.","triggerScenarios":"loadUIConfig with a .js file where bytes.TrimSpace(bytesConfig) does not match the UIConfig function regex: file defines UIConfig as a const arrow function, uses `export function UIConfig() {`, defines a differently named function, or the file is empty/HTML.","commonSituations":"Copying an ES-module style config (export const UIConfig = ...) from a modern JS project; renaming the function; pointing ui-config at a random .js bundle instead of a config; whitespace/encoding oddities from Windows line endings in unusual positions.","solutions":["Define the config as a plain `function UIConfig() { return {...}; }` at the top level of the file.","Remove `export` keywords and arrow-function syntax — Jaeger expects the classic function declaration.","Verify the file extension is .js and content is plain browser-side JS, not a module or bundle.","Check the file is non-empty and wasn't replaced by an HTML error page."],"exampleFix":"// before (ui-config.js)\nexport const UIConfig = () => ({ menu: [] });\n// after\nfunction UIConfig() {\n  return { menu: [] };\n}","handlingStrategy":"validation","validationCode":"re := regexp.MustCompile(`function\\s+UIConfig(\\s)?\\(\\s?\\)(\\s)?{`)\nif !re.Match(bytes.TrimSpace(jsBytes)) {\n    return fmt.Errorf(\"%s must define `function UIConfig() {`\", path)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always author UI configs as classic `function UIConfig() { return {...}; }`.","Avoid ES module syntax (export/arrow functions) in UI config files.","Add a unit test that loads your config with loadUIConfig before deploying."],"tags":["javascript","config","validation","jaeger-query"],"backgroundTag":"invalid-config-format","analyzedSha":"806f4447841ecdb60519f408b004a599d515f437","analyzedAt":"2026-09-01T02:39:22.140Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}