{"record":{"id":"a426b4ae8cc6c941","repo":"argoproj/argo-workflows","slug":"index-template-error-err-error","errorCode":null,"errorMessage":"index template error (err.Error())","messagePattern":"index template error \\(err\\.Error\\(\\)\\)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"server/static/static.go","lineNumber":56,"sourceCode":"\t\tif r.Method == http.MethodOptions { // Set CORS headers for preflight request\n\t\t\tw.Header().Set(\"Access-Control-Allow-Credentials\", \"true\")\n\t\t\tw.Header().Set(\"Access-Control-Allow-Methods\", \"POST, GET, OPTIONS, PUT, DELETE\")\n\t\t\tw.Header().Set(\"Access-Control-Allow-Headers\", \"Content-Type, Authorization\")\n\t\t\tw.WriteHeader(http.StatusNoContent)\n\t\t\treturn\n\t\t}\n\t}\n\n\t// `data:` is need for Monaco editors wiggly red lines\n\tw.Header().Set(\"Content-Security-Policy\", \"default-src 'self' 'unsafe-inline'; img-src 'self' data:\")\n\tif s.hsts {\n\t\tw.Header().Set(\"Strict-Transport-Security\", \"max-age=31536000\")\n\t}\n\n\tif r.URL.Path == \"/\" || !s.uiAssetExists(r.URL.Path) {\n\t\tdata, err := s.getIndexData()\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\n\t\tmodTime, err := time.Parse(argo.GetVersion().BuildDate, time.RFC3339)\n\t\tif err != nil {\n\t\t\tmodTime = time.Now()\n\t\t}\n\t\thttp.ServeContent(w, r, \"index.html\", modTime, bytes.NewReader(data))\n\t} else {\n\t\tstaticFS, _ := fs.Sub(s.staticAssets, ui.EMBED_PATH)\n\t\thttp.FileServer(http.FS(staticFS)).ServeHTTP(w, r)\n\t}\n}\n\nfunc (s *FilesServer) getIndexData() ([]byte, error) {\n\tdata, err := s.staticAssets.ReadFile(ui.EMBED_PATH + \"/index.html\")\n\tif err != nil {\n\t\treturn data, err","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/server/static/static.go#L38-L74","documentation":"ServerFiles (server/static/static.go:56) serves the embedded UI index.html for '/' and for any path that is not a known UI asset (SPA fallback). It fails with 500 when getIndexData() cannot read ui/dist/app/index.html from the embedded filesystem, or cannot apply the base-href rewrite. Since the assets are embedded at build time, this almost always means the binary was built without the UI assets embedded (e.g. `make start UI=false` or a stripped/custom build) or the baseHRef rewrite produced invalid data.","triggerScenarios":"Requesting the UI root path '/' (or any unknown path hitting the SPA fallback) against an argo-server binary built without the embedded UI assets (ui/dist/app/index.html missing from the embed.FS); or a custom staticAssets FS passed to NewFilesServer that lacks index.html.","commonSituations":"Running argo-server built with UI=false for lightweight/API-only use and then browsing to the server URL; custom Docker builds that skip the UI asset build step; running the binary from a directory-based build where `ui/dist` was never built (`make ui` skipped); custom baseHRef flags with a hand-crafted embed FS.","solutions":["Rebuild/redeploy argo-server with the UI included: build via `make cli` (or the official image) so ui/dist/app/index.html is embedded — a UI=false or stripped build cannot serve the UI","If you intended an API-only server, use the gRPC/HTTP API or `argo` CLI instead of opening the UI URL","If building a custom embed.FS, ensure it contains index.html under ui.EMBED_PATH before calling NewFilesServer","Run `make ui` in the repo so ui/dist exists before compiling the embedded assets"],"exampleFix":"// before: binary built without UI -> 500 on /\nmake start UI=false\n// after: build with UI assets embedded\nmake cli && ./dist/argo server","handlingStrategy":"fallback","validationCode":"// before serving, verify the UI assets are embedded in the binary\nif _, err := staticAssets.ReadFile(\"ui/dist/app/index.html\"); err != nil {\n    log.Fatal(\"argo-server built without UI assets; rebuild with `make cli` (not UI=false)\")\n}","typeGuard":"func uiAssetsEmbedded(assets embed.FS) bool {\n    f, err := assets.Open(\"ui/dist/app/index.html\")\n    if err != nil { return false }\n    f.Close()\n    return true\n}","tryCatchPattern":"// server-side fallback when index data is unavailable\nif _, err := s.getIndexData(); err != nil {\n    http.Error(w, \"UI not built into this binary; use the argo CLI or gRPC API\", http.StatusServiceUnavailable)\n    return\n}","preventionTips":["Never deploy a UI=false or asset-stripped binary where users will open the web UI","Build with the repo's own Makefile targets (`make cli`, `make controller`) so `ui/dist` is generated and embedded","In custom builds, run `make ui` before `go build` so the embed directory is populated","Smoke-test GET / on argo-server after each deployment to catch missing-asset builds immediately"],"tags":["http","static-assets","ui","embed"],"backgroundTag":"embedded-asset-missing","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}