{"record":{"id":"e6e1e784be10111f","repo":"apache/beam","slug":"failed-to-read-object-for-v","errorCode":null,"errorMessage":"Failed to read object for %v","messagePattern":"Failed to read object for (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/artifact/gcsproxy/retrieval.go","lineNumber":100,"sourceCode":"func (s *RetrievalServer) GetArtifact(req *jobpb.LegacyGetArtifactRequest, stream jobpb.LegacyArtifactRetrievalService_GetArtifactServer) error {\n\tkey := req.GetName()\n\tblob, ok := s.blobs[key]\n\tif !ok {\n\t\treturn errors.Errorf(\"artifact %v not found\", key)\n\t}\n\n\tbucket, object := parseObject(blob)\n\n\tctx := stream.Context()\n\tclient, err := gcsx.NewClient(ctx, storage.ScopeReadOnly)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"Failed to create client for %v\", key)\n\t}\n\n\t// Stream artifact in up to 1MB chunks.\n\tr, err := client.Bucket(bucket).Object(object).NewReader(ctx)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"Failed to read object for %v\", key)\n\t}\n\tdefer r.Close()\n\n\tdata := make([]byte, 1<<20)\n\tfor {\n\t\tn, err := r.Read(data)\n\t\tif n > 0 {\n\t\t\tif err := stream.Send(&jobpb.ArtifactChunk{Data: data[:n]}); err != nil {\n\t\t\t\treturn errors.Wrap(err, \"chunk send failed\")\n\t\t\t}\n\t\t}\n\t\tif err == io.EOF {\n\t\t\tbreak\n\t\t}\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"failed to read from %v\", blob)\n\t\t}\n\t}","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/artifact/gcsproxy/retrieval.go#L82-L118","documentation":"GetArtifact opens a GCS reader on the artifact object before streaming it in 1MB chunks. This wrapped error is returned when the GCS NewReader call fails, meaning the artifact object could not be opened for reading.","triggerScenarios":"Calling GetArtifact where the mapped blob URI points to a nonexistent, deleted, or permission-restricted object, so GCS returns 404/403 on reader creation.","commonSituations":"Artifact blobs garbage-collected after the manifest was created, bucket permissions changed, or blob URIs pointing to the wrong bucket after re-staging.","solutions":["Verify the object exists: gsutil stat gs://bucket/object from the manifest's blob URI.","Grant the retrieval service's account storage.objects.get on the artifact bucket.","Re-upload the artifacts and regenerate the manifest so blob URIs are current."],"exampleFix":"// before: reading from a stale manifest\nserver, _ := NewRetrievalServer(ctx, staleManifest)\n// after: rebuild server from a fresh manifest\nfresh, _ := ReadProxyManifest(ctx, manifestPath)\nserver, _ := NewRetrievalServer(ctx, fresh)","handlingStrategy":"fallback","validationCode":"func blobExists(ctx context.Context, cl *storage.Client, bucket, object string) bool { _, err := cl.Bucket(bucket).Object(object).Attrs(ctx); return err == nil }","typeGuard":null,"tryCatchPattern":"err := streamArtifact(ctx, key)\nif err != nil && strings.Contains(err.Error(), \"Failed to read object\") {\n    return fmt.Errorf(\"artifact blob %s unreadable (deleted or no access): %w\", key, err)\n}","preventionTips":["Apply retention/lifecycle rules so artifact blobs outlive the jobs that need them.","Re-read a fresh manifest if blob reads start failing with 404s."],"tags":["gcs","file-not-found","network","beam"],"backgroundTag":"resource-not-found","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}