{"record":{"id":"39c00e6c30ae420a","repo":"apache/beam","slug":"unable-to-start-sdk-worker-v-error-v-resp-v","errorCode":null,"errorMessage":"unable to start sdk worker %v error: %v, resp: %v","messagePattern":"unable to start sdk worker (.+?) error: (.+?), resp: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/runners/prism/internal/environments.go","lineNumber":152,"sourceCode":"\tendpoint := &pipepb.ApiServiceDescriptor{\n\t\tUrl: wk.Endpoint(),\n\t}\n\n\t// Use a background context for these workers to avoid pre-mature\n\t// cancelation issues when starting them.\n\tbgContext := context.Background()\n\n\tresp, err := pool.StartWorker(bgContext, &fnpb.StartWorkerRequest{\n\t\tWorkerId:          wk.ID,\n\t\tControlEndpoint:   endpoint,\n\t\tLoggingEndpoint:   endpoint,\n\t\tArtifactEndpoint:  endpoint,\n\t\tProvisionEndpoint: endpoint,\n\t\tParams:            ep.GetParams(),\n\t})\n\n\tif str := resp.GetError(); err != nil || str != \"\" {\n\t\tpanic(fmt.Sprintf(\"unable to start sdk worker %v error: %v, resp: %v\", ep.GetEndpoint().GetUrl(), err, prototext.Format(resp)))\n\t}\n\n\t// Job processing happens here, but orchestrated by other goroutines\n\t// This goroutine blocks until the context is cancelled, signalling\n\t// that the pool runner should stop the worker.\n\t<-ctx.Done()\n\n\t// Previous context cancelled so we need a new one\n\t// for this request.\n\tpool.StopWorker(bgContext, &fnpb.StopWorkerRequest{\n\t\tWorkerId: wk.ID,\n\t})\n\twk.Stop()\n}\n\nfunc dockerEnvironment(ctx context.Context, logger *slog.Logger, dp *pipepb.DockerPayload, wk *worker.W, artifactEndpoint string) error {\n\tlogger = logger.With(\"worker_id\", wk.ID, \"image\", dp.GetContainerImage())\n","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/runners/prism/internal/environments.go#L134-L170","documentation":"After dialing the external worker pool, externalEnvironment calls PrepareJob on the BeamFnExternalWorkerPoolClient. If the RPC returns an error or the response carries an error string, prism panics with the endpoint, the RPC error, and the prototext-formatted response.","triggerScenarios":"The external worker pool rejects the PrepareJob request: bad provisioning parameters, incompatible worker pool, artifact endpoint misconfiguration, or the pool side fails to start the SDK worker process.","commonSituations":"Version mismatch between runner and SDK harness worker pool, missing required params in environment_config, worker pool internal failure launching SDK workers, or artifact staging endpoint unreachable from the pool.","solutions":["Read the resp error text in the panic; it usually states why PrepareJob failed.","Verify environment params (e.g. SDK version, worker pool config) match what the pool expects.","Check the worker pool's own logs for the underlying launch failure.","Upgrade runner and SDK to matching versions so the external pool API is compatible."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Validate params before PrepareJob\nif len(params) == 0 || sdkVersion == \"\" {\n    return errors.New(\"environment params and SDK version required by external pool\")\n}","typeGuard":null,"tryCatchPattern":"resp, err := pool.PrepareJob(ctx, req)\nif err != nil {\n    return fmt.Errorf(\"PrepareJob failed: %w\", err)\n}\nif s := resp.GetError(); s != \"\" {\n    return fmt.Errorf(\"pool rejected job: %s\", s)\n}","preventionTips":["Match runner and SDK harness versions","Read the response error text for root cause","Check worker pool logs for launch failures"],"tags":["go","grpc","panic","worker-pool","beam"],"backgroundTag":"api-error-response","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"}