{"record":{"id":"5406c3bdac259d4c","repo":"kubernetes/kops","slug":"error-reading-directory-q-v","errorCode":null,"errorMessage":"error reading directory %q: %v","messagePattern":"error reading directory %q: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/vfs_castore.go","lineNumber":165,"sourceCode":"\tif !ok {\n\t\tklog.Fatalf(\"no YAML serializer registered\")\n\t}\n\tencoder := codecs.EncoderForVersion(yaml.Serializer, v1alpha2.SchemeGroupVersion)\n\n\tif err := encoder.Encode(o, &objectData); err != nil {\n\t\treturn nil, fmt.Errorf(\"error serializing keyset: %v\", err)\n\t}\n\treturn objectData.Bytes(), nil\n}\n\n// ListKeysets implements CAStore::ListKeysets\nfunc (c *VFSCAStore) ListKeysets() (map[string]*Keyset, error) {\n\tctx := context.TODO()\n\n\tbaseDir := c.basedir.Join(\"private\")\n\tfiles, err := baseDir.ReadTree(ctx)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error reading directory %q: %v\", baseDir, err)\n\t}\n\n\tkeysets := map[string]*Keyset{}\n\n\tfor _, f := range files {\n\t\trelativePath, err := vfs.RelativePath(baseDir, f)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\ttokens := strings.Split(relativePath, \"/\")\n\t\tif len(tokens) != 2 || tokens[1] != \"keyset.yaml\" {\n\t\t\tklog.V(2).Infof(\"ignoring unexpected file in keystore: %q\", f)\n\t\t\tcontinue\n\t\t}\n\n\t\tname := tokens[0]\n\t\tloadedKeyset, err := c.loadKeyset(ctx, baseDir.Join(name))","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/vfs_castore.go#L147-L183","documentation":"VFSCAStore.ListKeysets reads the entire tree under <state-store>/<cluster>/private via vfs ReadTree to discover keysets. If the underlying storage (S3/GCS/etc.) read fails — permissions, missing bucket, network issues — the error is wrapped as \"error reading directory\" with the base path.","triggerScenarios":"Calling ListKeysets (or MirrorTo which uses related listing) when the state store path is inaccessible: bucket does not exist, credentials lack s3:ListBucket/GetObject, region mismatch, network outage, or the VFS path is misconfigured.","commonSituations":"Running `kops get secrets`/mirror commands with wrong --state or KOPS_STATE_STORE; IAM policies changed or creds expired; offline/blocked network access to the cloud storage endpoint; typo'd bucket name.","solutions":["Verify KOPS_STATE_STORE/--state points to an existing, correctly-spelled bucket/path.","Check cloud credentials and IAM permissions for listing/reading objects in the bucket.","Confirm network access to the storage endpoint and correct region configuration.","Run `kops get clusters` against the same state store to isolate whether the path or permissions are the problem."],"exampleFix":"// before\nexport KOPS_STATE_STORE=s3://kops-state-backup  # bucket does not exist\n// after\nexport KOPS_STATE_STORE=s3://my-kops-state  # existing bucket with read access","handlingStrategy":"retry","validationCode":"// Verify the state store is readable before listing\nctx := context.TODO()\nif _, err := vfs.Context.ReadLocation(os.Getenv(\"KOPS_STATE_STORE\")).Join(cluster.Name).Join(\"config\").ReadFile(ctx); err != nil {\n\treturn fmt.Errorf(\"state store unreadable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"keysets, err := store.ListKeysets()\nif err != nil {\n\tif strings.Contains(err.Error(), \"error reading directory\") {\n\t\t// check creds/bucket, optionally retry with backoff\n\t\treturn retryWithBackoff(func() error { _, e := store.ListKeysets(); return e })\n\t}\n\treturn err\n}","preventionTips":["Pin KOPS_STATE_STORE in CI and verify bucket existence in a preflight step.","Grant least-privilege read (List/Get) IAM policies to the identity running kops.","Handle transient cloud-storage errors with exponential backoff."],"tags":["storage","vfs","state-store","permissions"],"backgroundTag":"state-store-unreadable","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}