{"record":{"id":"35ea589fbaa5f7d3","repo":"derailed/k9s","slug":"no-path-specified-in-context","errorCode":null,"errorMessage":"no path specified in context","messagePattern":"no path specified in context","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/dao/benchmark.go","lineNumber":50,"sourceCode":"// Delete nukes a resource.\nfunc (*Benchmark) Delete(_ context.Context, path string, _ *metav1.DeletionPropagation, _ Grace) error {\n\treturn os.Remove(path)\n}\n\n// Get returns a resource.\nfunc (*Benchmark) Get(context.Context, string) (runtime.Object, error) {\n\tpanic(\"NYI\")\n}\n\n// List returns a collection of resources.\nfunc (*Benchmark) List(ctx context.Context, _ string) ([]runtime.Object, error) {\n\tdir, ok := ctx.Value(internal.KeyDir).(string)\n\tif !ok {\n\t\treturn nil, errors.New(\"no benchmark dir found in context\")\n\t}\n\tpath, ok := ctx.Value(internal.KeyPath).(string)\n\tif !ok {\n\t\treturn nil, errors.New(\"no path specified in context\")\n\t}\n\tpathMatch := BenchRx.ReplaceAllString(strings.Replace(path, \"/\", \"_\", 1), \"_\")\n\n\tff, err := os.ReadDir(dir)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\too := make([]runtime.Object, 0, len(ff))\n\tfor _, f := range ff {\n\t\tif !strings.HasPrefix(f.Name(), pathMatch) {\n\t\t\tcontinue\n\t\t}\n\t\tif fi, err := f.Info(); err == nil {\n\t\t\too = append(oo, render.BenchInfo{File: fi, Path: filepath.Join(dir, f.Name())})\n\t\t}\n\t}\n\n\treturn oo, nil","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/derailed/k9s/blob/2d3ccc6ba2ce98c3781bfc441bb3e884f072774f/internal/dao/benchmark.go#L32-L68","documentation":"Returned by Benchmark DAO List (internal/dao/benchmark.go:50) when the context carries no internal.KeyPath string value. KeyPath selects which benchmark files to match: it is normalized (slashes replaced by '_' in its first segment, then BenchRx) into pathMatch used to filter os.ReadDir results by filename prefix. Missing/incorrectly-typed KeyPath aborts listing even when KeyDir was supplied.","triggerScenarios":"Calling List with KeyDir set but no context.WithValue(ctx, internal.KeyPath, p); storing a non-string under the key; or passing an empty-path variant of the call that skips enrichment.","commonSituations":"Same as [12] — custom DAO callers, tests, refactors losing the WithValue chain; navigating to the benchmark view root where code assumed a default path instead of injecting one.","solutions":["Always pair both keys: WithValue(ctx, internal.KeyDir, dir) and WithValue(ctx, internal.KeyPath, path)","Check the value type is exactly string (the ok from ctx.Value(...).(string)) — an int or custom type will fail the assertion","Route calls through the view layer that builds this context; keep DAO usage internal"],"exampleFix":"// before\nctx := context.WithValue(context.Background(), internal.KeyDir, dir)\noo, err := bench.List(ctx, \"\")\n\n// after\nctx := context.WithValue(ctx, internal.KeyPath, \"allocs/scan\")\noo, err := bench.List(ctx, \"\")","handlingStrategy":"validation","validationCode":"func benchCtx(dir, path string) context.Context {\n    ctx := context.WithValue(context.Background(), internal.KeyDir, dir)\n    return context.WithValue(ctx, internal.KeyPath, path)\n}","typeGuard":null,"tryCatchPattern":"oo, err := benchDao.List(ctx, \"\")\nif err != nil && strings.Contains(err.Error(), \"no path specified in context\") {\n    ctx = context.WithValue(ctx, internal.KeyPath, wantPath)\n    oo, err = benchDao.List(ctx, \"\")\n}","preventionTips":["Set KeyDir and KeyPath together in one helper — they are only valid as a pair","Assert both keys in tests before exercising Benchmark.List","Avoid ad-hoc WithValue sprinkled at multiple layers"],"tags":["go","context","k9s","benchmarks","dao"],"backgroundTag":null,"analyzedSha":"2d3ccc6ba2ce98c3781bfc441bb3e884f072774f","analyzedAt":"2026-08-15T16:09:14.432Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}