{"record":{"id":"e9b4fac1d1d5040e","repo":"kubernetes/kops","slug":"error-writing-secret-q-for-mirror-v","errorCode":null,"errorMessage":"error writing secret %q for mirror: %v","messagePattern":"error writing secret %q for mirror: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/secrets/vfs_secretstore.go","lineNumber":83,"sourceCode":"\t\t\treturn fmt.Errorf(\"error reading secret %q for mirror: %v\", name, err)\n\t\t}\n\n\t\tif secret == nil {\n\t\t\treturn fmt.Errorf(\"unable to find secret %q for mirror\", name)\n\t\t}\n\n\t\tp := BuildVfsSecretPath(basedir, name)\n\n\t\tacl, err := acls.GetACL(ctx, p, c.cluster)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error building acl for secret %q for mirror: %v\", name, err)\n\t\t}\n\n\t\tklog.Infof(\"mirroring secret %s -> %s\", name, p)\n\n\t\terr = createSecret(ctx, secret, p, acl, true)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error writing secret %q for mirror: %v\", name, err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// DeleteSecret implements fi.SecretStore DeleteSecret\nfunc (c *VFSSecretStore) DeleteSecret(name string) error {\n\tctx := context.TODO()\n\n\tp := c.buildSecretPath(name)\n\treturn p.Remove(ctx)\n}\n\nfunc (c *VFSSecretStore) ListSecrets() ([]string, error) {\n\tfiles, err := c.basedir.ReadDir()\n\tvar ids []string\n\tif os.IsNotExist(err) {","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/secrets/vfs_secretstore.go#L65-L101","documentation":"The final step of mirroring each secret is createSecret(..., replace=true), which JSON-serializes the secret and calls p.WriteFile on the destination path. If the write fails (storage error, permission denied, ACL rejected, or — less commonly — serialization failure inside createSecret), MirrorTo wraps it as 'error writing secret %q for mirror'.","triggerScenarios":"Writing <target-basdir>/<name> fails: no write access to destination bucket/prefix, object-lock/versioning conflicts, quota exceeded, or the destination is a directory-like key that cannot be overwritten.","commonSituations":"Mirroring secrets into a read-only or other account's S3 bucket, S3 bucket policy denying s3:PutObject, running out of GCS quota, or the destination path already holding an undeletable object.","solutions":["Test write access to the destination: `aws s3 cp` a dummy file into the prefix","Grant s3:PutObject (or GCS equivalent) on the destination bucket/prefix to your principal","Remove conflicting objects at the destination path","Check the wrapped %v cause — if it says 'serializing', the secret itself cannot be JSON-marshaled (rare; usually means corrupted in-memory state)"],"exampleFix":"// before: destination bucket policy denies writes\nstore.MirrorTo(ctx, target) // error writing secret \"dockerconfig\" for mirror: AccessDenied\n// after: grant put permission first\n// aws s3api put-bucket-policy --bucket dest-bucket --policy file://allow-put.json\nerr := store.MirrorTo(ctx, target)","handlingStrategy":"try-catch","validationCode":"// Probe write access before mirroring\nprobe := secrets.BuildVfsSecretPath(target, \".write-probe\")\nif err := probe.WriteFile(ctx, strings.NewReader(\"probe\"), nil); err != nil {\n    return fmt.Errorf(\"no write access to destination: %v\", err)\n}\n_ = probe.Remove(ctx)","typeGuard":null,"tryCatchPattern":"if err := store.MirrorTo(ctx, target); err != nil {\n    if strings.Contains(err.Error(), \"error writing secret\") {\n        return fmt.Errorf(\"check PutObject on destination bucket: %v\", err)\n    }\n    return err\n}","preventionTips":["Grant write (PutObject/storage.objects.create) on the destination prefix","Test with a dummy object upload before bulk mirroring","Watch for bucket policies/object-lock that block overwrites","Check quotas on the destination storage"],"tags":["vfs","secrets","write-failed","mirror"],"backgroundTag":"secret-write-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"}