{"record":{"id":"cb9d72b46ec50899","repo":"derailed/k9s","slug":"no-dir-in-context","errorCode":null,"errorMessage":"no dir in context","messagePattern":"no dir in context","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/dao/dir.go","lineNumber":40,"sourceCode":"// Dir tracks standard and custom command aliases.\ntype Dir struct {\n\tNonResource\n}\n\n// NewDir returns a new set of aliases.\nfunc NewDir(f Factory) *Dir {\n\tvar a Dir\n\ta.Init(f, client.DirGVR)\n\treturn &a\n}\n\nvar yamlRX = regexp.MustCompile(`.*\\.(yml|yaml|json)`)\n\n// List returns a collection of aliases.\nfunc (*Dir) List(ctx context.Context, _ string) ([]runtime.Object, error) {\n\tdir, ok := ctx.Value(internal.KeyPath).(string)\n\tif !ok {\n\t\treturn nil, errors.New(\"no dir in context\")\n\t}\n\n\tfiles, err := os.ReadDir(dir)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\too := make([]runtime.Object, 0, len(files))\n\tfor _, f := range files {\n\t\tif strings.HasPrefix(f.Name(), \".\") || !f.IsDir() && !yamlRX.MatchString(f.Name()) {\n\t\t\tcontinue\n\t\t}\n\t\too = append(oo, render.DirRes{\n\t\t\tPath:  filepath.Join(dir, f.Name()),\n\t\t\tEntry: f,\n\t\t})\n\t}\n","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/derailed/k9s/blob/2d3ccc6ba2ce98c3781bfc441bb3e884f072774f/internal/dao/dir.go#L22-L58","documentation":"Dir is the DAO behind the local directory browser (view/dir.go) and reads the local filesystem, not the cluster. Because its List signature has no path parameter, the directory to browse must be carried in the context under internal.KeyPath as a string (internal/dao/dir.go:40). If the key is absent — not merely empty — List returns 'no dir in context' before touching the disk.","triggerScenarios":"Calling dao.Dir.List(ctx, \"\") with a context that never had context.WithValue(ctx, internal.KeyPath, dir). The stock views always inject it via view/dir.go's context function, so this is hit mainly in unit tests (compare internal/dao/dir_test.go which seeds it), plugins, or embedding code that passes context.Background().","commonSituations":"Programmatic use of the DAO layer outside the TUI; refactors that build a fresh context for a browser view and forget the path key; storing a non-string value under KeyPath so the type assertion fails (also reported as 'no dir in context').","solutions":["Seed the key before listing: ctx = context.WithValue(ctx, internal.KeyPath, \"/path/to/dir\").","When writing views, reuse the contextFn pattern from internal/view/dir.go instead of hand-building contexts.","Ensure the value is a plain string; any other type fails the ctx.Value assertion silently.","In tests, mirror internal/dao/dir_test.go which sets KeyPath to a testdata directory."],"exampleFix":"// before\nctx := context.Background()\nitems, err := dirDAO.List(ctx, \"\") // -> no dir in context\n// after\nctx := context.WithValue(context.Background(), internal.KeyPath, \"/tmp/mydir\")\nitems, err := dirDAO.List(ctx, \"\")","handlingStrategy":"validation","validationCode":"if _, ok := ctx.Value(internal.KeyPath).(string); !ok {\n    ctx = context.WithValue(ctx, internal.KeyPath, dirPath)\n}\nitems, err := dirDAO.List(ctx, \"\")","typeGuard":"func dirFrom(ctx context.Context) (string, bool) {\n    d, ok := ctx.Value(internal.KeyPath).(string)\n    return d, ok\n}","tryCatchPattern":null,"preventionTips":["Never call dao.Dir.List with context.Background(); always pair it with KeyPath.","Reuse the view/dir.go context function instead of hand-building contexts.","Remember the value must be a string; other types fail the assertion as 'no dir in context'.","Seed context keys in unit tests exactly as internal/dao/dir_test.go does."],"tags":["go","context","filesystem","dao"],"backgroundTag":null,"analyzedSha":"2d3ccc6ba2ce98c3781bfc441bb3e884f072774f","analyzedAt":"2026-08-15T16:09:14.432Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}