{"record":{"id":"6a59a8c9e8dd54a5","repo":"geektutu/7days-golang","slug":"rpc-client-call-failed-6a59a8","errorCode":null,"errorMessage":"rpc client: call failed: ","messagePattern":"rpc client: call failed: ","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"gee-rpc/day7-registry/client.go","lineNumber":191,"sourceCode":"\t}\n\tcall := &Call{\n\t\tServiceMethod: serviceMethod,\n\t\tArgs:          args,\n\t\tReply:         reply,\n\t\tDone:          done,\n\t}\n\tclient.send(call)\n\treturn call\n}\n\n// Call invokes the named function, waits for it to complete,\n// and returns its error status.\nfunc (client *Client) Call(ctx context.Context, serviceMethod string, args, reply interface{}) error {\n\tcall := client.Go(serviceMethod, args, reply, make(chan *Call, 1))\n\tselect {\n\tcase <-ctx.Done():\n\t\tclient.removeCall(call.Seq)\n\t\treturn errors.New(\"rpc client: call failed: \" + ctx.Err().Error())\n\tcase call := <-call.Done:\n\t\treturn call.Error\n\t}\n}\n\nfunc parseOptions(opts ...*Option) (*Option, error) {\n\t// if opts is nil or pass nil as parameter\n\tif len(opts) == 0 || opts[0] == nil {\n\t\treturn DefaultOption, nil\n\t}\n\tif len(opts) != 1 {\n\t\treturn nil, errors.New(\"number of options is more than 1\")\n\t}\n\topt := opts[0]\n\topt.MagicNumber = DefaultOption.MagicNumber\n\tif opt.CodecType == \"\" {\n\t\topt.CodecType = DefaultOption.CodecType\n\t}","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/geektutu/7days-golang/blob/cf3644382101dc13e7fd92e8f5c66cabc51bcd3b/gee-rpc/day7-registry/client.go#L173-L209","documentation":"The context passed to Call was cancelled or its deadline expired while waiting for the async Go() call to finish. The library removes the pending call by seq and wraps ctx.Err() as \"rpc client: call failed: \" + reason. The RPC itself may still complete server-side.","triggerScenarios":"context.WithTimeout deadline elapsing before the server responds; explicit cancel() from another goroutine; calling with an already-cancelled context; server too slow under load.","commonSituations":"Tight timeouts on slow RPCs (large payloads, cold-start), cascading cancellation from upstream request context, forgetting to pass context.Background() for fire-and-forget usage, or a hung server (e.g. deadlock) exceeding the deadline.","solutions":["Increase the context timeout to cover realistic server latency.","Verify the server method's performance; fix slowness/deadlocks causing timeouts.","Use context.Background() (or a detached context) when the call should not be tied to a request lifecycle.","Make the call idempotent and retry with a fresh context if the operation is safe to repeat."],"exampleFix":"// before\nctx, _ := context.WithTimeout(context.Background(), 10*time.Millisecond)\nerr := client.Call(ctx, \"Foo.Sum\", req, reply) // deadline exceeded\n// after\nctx, _ := context.WithTimeout(context.Background(), 3*time.Second)\nerr := client.Call(ctx, \"Foo.Sum\", req, reply)","handlingStrategy":"try-catch","validationCode":"deadline, ok := ctx.Deadline()\nif ok && time.Until(deadline) < expectedLatency {\n    // extend deadline or warn before making the call\n}","typeGuard":null,"tryCatchPattern":"if err := client.Call(ctx, \"Foo.Sum\", args, reply); err != nil && strings.HasPrefix(err.Error(), \"rpc client: call failed: \") {\n    if errors.Is(ctx.Err(), context.DeadlineExceeded) { /* retry with fresh context */ }\n}","preventionTips":["Budget timeouts generously for large payloads and cold paths.","Make RPCs idempotent so a timed-out call can be safely retried.","Avoid propagating short-lived HTTP request contexts into slow RPCs without extending the deadline."],"tags":["rpc","context","timeout","client"],"backgroundTag":"context-deadline-exceeded","analyzedSha":"cf3644382101dc13e7fd92e8f5c66cabc51bcd3b","analyzedAt":"2026-09-03T18:31:24.087Z","contentChangedAt":"2026-09-03T18:31:24.087Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}