{"record":{"id":"5a17b4a38e8eb779","repo":"apache/beam","slug":"invalid-hook-configuration-for-gcsrecorderhook-s","errorCode":null,"errorMessage":"Invalid hook configuration for gcsRecorderHook: %s","messagePattern":"Invalid hook configuration for gcsRecorderHook: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/runners/dataflow/dataflow.go","lineNumber":439,"sourceCode":"\t\tWorkerZone:                     *workerZone,\n\t\tTeardownPolicy:                 *teardownPolicy,\n\t\tContainerImage:                 getContainerImage(ctx),\n\t\tUpdate:                         *update,\n\t\tTransformNameMapping:           updateTransformMapping,\n\t}\n\tif opts.TempLocation == \"\" {\n\t\topts.TempLocation = gcsx.Join(*stagingLocation, \"tmp\")\n\t}\n\n\tcheckSoftDeletePolicyEnabled(ctx, opts.TempLocation, \"temp_location\")\n\n\treturn opts, nil\n}\n\nfunc gcsRecorderHook(opts []string) perf.CaptureHook {\n\tbucket, prefix, err := gcsx.ParseObject(opts[0])\n\tif err != nil {\n\t\tpanic(fmt.Sprintf(\"Invalid hook configuration for gcsRecorderHook: %s\", opts))\n\t}\n\n\treturn func(ctx context.Context, spec string, r io.Reader) error {\n\t\tclient, err := gcsx.NewClient(ctx, storage.ScopeReadWrite)\n\t\tif err != nil {\n\t\t\treturn errors.WithContext(err, \"establishing GCS client\")\n\t\t}\n\t\treturn gcsx.WriteObject(ctx, client, bucket, path.Join(prefix, spec), r)\n\t}\n}\n\nfunc getContainerImage(ctx context.Context) string {\n\turn := jobopts.GetEnvironmentUrn(ctx)\n\tif urn == \"\" || urn == \"beam:env:docker:v1\" {\n\t\tif *workerHarnessImage != \"\" {\n\t\t\tif *image != \"\" {\n\t\t\t\tpanic(\"Both worker_harness_container_image and sdk_container_image cannot both be set. Prefer sdk_container_image, worker_harness_container_image is deprecated.\")\n\t\t\t}","sourceCodeStart":421,"sourceCodeEnd":457,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/runners/dataflow/dataflow.go#L421-L457","documentation":"The --performance_recording_hook=gcsRecorderHook option expects its argument to be a valid GCS object reference like bucket/path/prefix. gcsRecorderHook parses opts[0] with gcsx.ParseObject and panics if the string is not a parseable GCS object path.","triggerScenarios":"Passing a malformed value to the perf capture hook, e.g. --experiment=performance_recording_hook=gcsRecorderHook,nota,gcs,path or an option string without a bucket-qualified object path (missing bucket or empty string).","commonSituations":"Typos in the Dataflow job option, forgetting the gs://-style bucket prefix format expected by ParseObject, or passing extra comma-separated fields that corrupt opts[0].","solutions":["Provide a well-formed GCS object path as the first hook option, e.g. my-bucket/path/to/prefix","Verify the option format: gcsRecorderHook,<bucket>/<object-path>","Log the opts value and test gcsx.ParseObject on it locally before submitting the job","Remove the performance recording experiment if GCS recording is not needed"],"exampleFix":"// before\n--experiment=performance_recording_hook=gcsRecorderHook,myfolder\n// after\n--experiment=performance_recording_hook=gcsRecorderHook,my-bucket/perf/prefix","handlingStrategy":"validation","validationCode":"opts := strings.SplitN(hookArg, \",\", 2)\nif len(opts) < 2 || !strings.Contains(opts[1], \"/\") {\n    return fmt.Errorf(\"gcsRecorderHook requires bucket/object path, got %q\", hookArg)\n}\nif _, _, err := gcsx.ParseObject(opts[1]); err != nil {\n    return err\n}","typeGuard":null,"tryCatchPattern":"func safeHook(opts []string) (perf.CaptureHook, err error) {\n    defer func() { if r := recover(); r != nil { err = fmt.Errorf(\"bad hook config: %v\", r) } }()\n    return gcsRecorderHook(opts), nil\n}","preventionTips":["Validate the hook argument format before launching the job","Use full bucket-qualified paths: bucket/folder/prefix","Test ParseObject on the configured string locally","Keep hook configuration in version-controlled launch scripts"],"tags":["gcs","dataflow","config"],"backgroundTag":"invalid-config-value","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"}