{"record":{"id":"2649fc65cbeb5d30","repo":"kubernetes/kops","slug":"reading-tree-w","errorCode":null,"errorMessage":"reading tree: %w","messagePattern":"reading tree: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/commands/toolbox_enroll.go","lineNumber":906,"sourceCode":"\t\t\t*pSrc = dest\n\t\t\treturn nil\n\t\t}\n\n\t\t// remapTree remaps a file tree from s3/gcs etc to the local file system on the target node.\n\t\tremapTree := func(pSrc *string, dest string) error {\n\t\t\tsrc := *pSrc\n\t\t\tif !strings.HasPrefix(src, remapPrefix) {\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\tsrcPath, err := vfsContext.BuildVfsPath(src)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"building vfs path: %w\", err)\n\t\t\t}\n\n\t\t\tsrcFiles, err := srcPath.ReadTree(ctx)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"reading tree: %w\", err)\n\t\t\t}\n\t\t\tbasePath := srcPath.Path()\n\t\t\tfor _, srcFile := range srcFiles {\n\t\t\t\tb, err := srcFile.ReadFile(ctx)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"reading file: %w\", err)\n\t\t\t\t}\n\n\t\t\t\tif !strings.HasPrefix(srcFile.Path(), basePath) {\n\t\t\t\t\treturn fmt.Errorf(\"unexpected path: %q\", srcFile.Path())\n\t\t\t\t}\n\t\t\t\trelativePath := strings.TrimPrefix(srcFile.Path(), basePath)\n\n\t\t\t\tbootstrapData.NodeupScriptAdditionalFiles[path.Join(dest, relativePath)] = b\n\t\t\t}\n\n\t\t\t*pSrc = dest\n\t\t\treturn nil","sourceCodeStart":888,"sourceCodeEnd":924,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/commands/toolbox_enroll.go#L888-L924","documentation":"After building the directory path, srcPath.ReadTree(ctx) enumerates all objects under the prefix. If the tree read fails — prefix missing, listing permission denied, backend error — the failure is wrapped as 'reading tree: %w' and bootstrap-data building stops.","triggerScenarios":"BuildVfsPath succeeded on the directory prefix but ReadTree fails: prefix does not exist, caller lacks s3:ListBucket / storage.objects.list permission, or a transient backend error during listing.","commonSituations":"Directory emptied or renamed in the state store; IAM policy allows GetObject but not ListBucket; throttling during large listings; wrong region endpoint for the bucket.","solutions":["Read the wrapped cause to distinguish not-found vs permission vs throttling.","Verify the prefix exists and contains files: `aws s3 ls s3://bucket/prefix/`.","Grant list permission (s3:ListBucket / objectViewer role) to the caller.","Retry with backoff for transient listing errors."],"exampleFix":"// before\nsrcFiles, err := srcPath.ReadTree(ctx) // fails: s3:ListBucket denied\n// after\n// IAM: add {\"Effect\":\"Allow\",\"Action\":\"s3:ListBucket\",\"Resource\":\"arn:aws:s3:::bucket\"}\nsrcFiles, err := srcPath.ReadTree(ctx)","handlingStrategy":"retry","validationCode":"// Ensure the prefix lists successfully before ReadTree\n// aws s3 ls s3://bucket/prefix/  (must return objects, not AccessDenied)","typeGuard":null,"tryCatchPattern":"if err != nil {\n\tvar notFound *NotFoundError\n\tif errors.As(err, &notFound) {\n\t\treturn fmt.Errorf(\"directory %s missing from state store\", src)\n\t}\n\treturn retry.WithBackoff(func() error { _, err := srcPath.ReadTree(ctx); return err }, 3)\n}","preventionTips":["Grant list permissions (s3:ListBucket / storage.objects.list), not just read","Do not rename/empty asset directories referenced by nodeup scripts","Use requester-pays/region-correct endpoints to avoid listing errors"],"tags":["kops","vfs","readtree","permissions"],"backgroundTag":"vfs-tree-read-failed","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}