{"record":{"id":"d6d508660fbd99b7","repo":"apache/beam","slug":"failed-to-send-header-for-v","errorCode":null,"errorMessage":"failed to send header for %v","messagePattern":"failed to send header for (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/artifact/stage.go","lineNumber":158,"sourceCode":"\tfd, err := os.Open(filename)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer fd.Close()\n\n\tstream, err := client.PutArtifact(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\theader := &jobpb.PutArtifactRequest{\n\t\tContent: &jobpb.PutArtifactRequest_Metadata{\n\t\t\tMetadata: pmd,\n\t\t},\n\t}\n\tif err := stream.Send(header); err != nil {\n\t\tstream.CloseAndRecv() // ignore error\n\t\treturn nil, errors.Wrapf(err, \"failed to send header for %v\", filename)\n\t}\n\tstagedHash, err := stageChunks(stream, fd)\n\tif err != nil {\n\t\t_, errClose := stream.CloseAndRecv()\n\t\treturn nil, errors.Wrapf(err, \"failed to send chunks for %v; close error: %v\", filename, errClose)\n\t}\n\tif resp, err := stream.CloseAndRecv(); err != nil && err != io.EOF {\n\t\treturn nil, errors.Wrapf(err, \"failed to close stream for %v; response: %v\", filename, resp)\n\t}\n\tif hash != stagedHash {\n\t\treturn nil, errors.Errorf(\"unexpected SHA256 for sent chunks for %v: %v, want %v\", filename, stagedHash, hash)\n\t}\n\treturn md, nil\n}\n\nfunc stageChunks(stream jobpb.LegacyArtifactStagingService_PutArtifactClient, r io.Reader) (string, error) {\n\tsha256W := sha256.New()\n\tdata := make([]byte, 1<<20)","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/artifact/stage.go#L140-L176","documentation":"Stage sends the PutArtifact header (metadata message) as the first stream message; if stream.Send fails, the stream is closed and the error wrapped with this message. It means the very first message of the artifact upload was rejected by the gRPC layer, before any file content was transmitted.","triggerScenarios":"Calling artifact.Stage (directly or via MultiStage) where the initial stream.Send(header) returns an error: connection broken immediately after PutArtifact was opened, context canceled/deadline exceeded, or the server closed the stream (e.g. invalid staging token handled via status instead of Send acceptance).","commonSituations":"Runner endpoint went down between connection setup and header send; submitting context times out on slow links; invalid staging session token causing the server to abort the stream; firewall/proxy killing the gRPC connection.","solutions":["Read the wrapped gRPC status (Unavailable, Canceled, Unknown) to pinpoint transport vs server rejection.","Verify the staging session token is valid and not expired before staging.","Check connectivity to the artifact staging endpoint (port open, TLS certs correct).","Retry — MultiStage retries up to 3 times with jittered backoff; use it rather than single Stage calls."],"exampleFix":"// before\nmd, err := artifact.Stage(ctx, client, key, filename, st)\n// after — use the retrying wrapper\nartifacts, err := artifact.MultiStage(ctx, client, 4, []artifact.FileArtifact{{Key: key, Filename: filename}}, st)\nif err != nil {\n    return err\n}","handlingStrategy":"retry","validationCode":"conn, err := grpc.DialContext(ctx, endpoint, grpc.WithBlock(), grpc.WithTimeout(5*time.Second))\nif err != nil {\n    return fmt.Errorf(\"cannot reach staging endpoint: %w\", err)\n}\nif _, err := os.Stat(filename); err != nil {\n    conn.Close()\n    return fmt.Errorf(\"cannot stage missing file: %w\", err)\n}\nconn.Close()","typeGuard":null,"tryCatchPattern":"if _, err := artifact.Stage(ctx, client, key, filename, st); err != nil {\n    if strings.Contains(err.Error(), \"failed to send header\") && st, ok := status.FromError(errors.Unwrap(err)); ok && st.Code() == codes.Unavailable {\n        time.Sleep(3 * time.Second)\n        _, err = artifact.Stage(ctx, client, key, filename, st)\n    }\n    return err\n}","preventionTips":["Use MultiStage for automatic retries with jittered backoff","Check endpoint reachability and TLS before submitting jobs","Keep the staging context deadline generous relative to link speed","Validate staging tokens before opening the upload stream"],"tags":["grpc","streaming","network","artifact"],"backgroundTag":"network-request-failed","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}