{"record":{"id":"79b89200e15ba053","repo":"apache/pulsar","slug":"failed-to-unmarshal-consume-specs-v","errorCode":null,"errorMessage":"Failed to unmarshal consume specs: %v","messagePattern":"Failed to unmarshal consume specs: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"pulsar-function-go/pf/instanceConf.go","lineNumber":71,"sourceCode":"\ttlsHostnameVerification     bool\n}\n\nfunc newInstanceConfWithConf(cfg *conf.Conf) *instanceConf {\n\tinputSpecs := make(map[string]*pb.ConsumerSpec)\n\t// for backward compatibility\n\tif cfg.SourceSpecTopic != \"\" {\n\t\tinputSpecs[cfg.SourceSpecTopic] = &pb.ConsumerSpec{\n\t\t\tSchemaType:     cfg.SourceSchemaType,\n\t\t\tIsRegexPattern: cfg.IsRegexPatternSubscription,\n\t\t\tReceiverQueueSize: &pb.ConsumerSpec_ReceiverQueueSize{\n\t\t\t\tValue: cfg.ReceiverQueueSize,\n\t\t\t},\n\t\t}\n\t}\n\tfor topic, value := range cfg.SourceInputSpecs {\n\t\tspec := &pb.ConsumerSpec{}\n\t\tif err := json.Unmarshal([]byte(value), spec); err != nil {\n\t\t\tpanic(fmt.Sprintf(\"Failed to unmarshal consume specs: %v\", err))\n\t\t}\n\t\tinputSpecs[topic] = spec\n\t}\n\tinstanceConf := &instanceConf{\n\t\tinstanceID:                  cfg.InstanceID,\n\t\tfuncID:                      cfg.FuncID,\n\t\tfuncVersion:                 cfg.FuncVersion,\n\t\tmaxBufTuples:                cfg.MaxBufTuples,\n\t\tport:                        cfg.Port,\n\t\tclusterName:                 cfg.ClusterName,\n\t\tpulsarServiceURL:            cfg.PulsarServiceURL,\n\t\tstateServiceURL:             cfg.StateStorageServiceURL,\n\t\tpulsarWebServiceURL:         cfg.PulsarWebServiceURL,\n\t\tkillAfterIdle:               cfg.KillAfterIdleMs,\n\t\texpectedHealthCheckInterval: cfg.ExpectedHealthCheckInterval,\n\t\tmetricsPort:                 cfg.MetricsPort,\n\t\tfuncDetails: pb.FunctionDetails{\n\t\t\tTenant:               cfg.Tenant,","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-function-go/pf/instanceConf.go#L53-L89","documentation":"newInstanceConfWithConf decodes each entry of SourceInputSpecs (a map of topic -> JSON string) into a pb.ConsumerSpec. If any value is not valid JSON, the instance config construction panics with this message, crashing the function instance at startup.","triggerScenarios":"A SourceInputSpecs value that isn't valid JSON for ConsumerSpec, e.g. an empty string, plain topic name, or truncated/invalid JSON produced by the function worker config serialization.","commonSituations":"Manual conf file edits introducing malformed JSON; upstream framework passing raw values instead of serialized ConsumerSpec; encoding bugs between worker and Go instance.","solutions":["Validate each SourceInputSpecs value parses as a ConsumerSpec JSON object (e.g. {\"schemaType\":\"...\",\"receiverQueueSize\":...}).","Fix the component that populates SourceInputSpecs (usually the function worker) to serialize specs properly.","Catch the panic in a wrapper during local testing to surface the offending topic/value."],"exampleFix":"// before\n\"sourceInputSpecs\": {\"topic-a\": \"\"} // panics on unmarshal\n// after\n\"sourceInputSpecs\": {\"topic-a\": \"{\\\"receiverQueueSize\\\":0}\"}","handlingStrategy":"validation","validationCode":"for topic, raw := range sourceInputSpecs {\n    var spec pb.ConsumerSpec\n    if err := json.Unmarshal([]byte(raw), &spec); err != nil {\n        return fmt.Errorf(\"invalid ConsumerSpec JSON for topic %s: %w\", topic, err)\n    }\n}","typeGuard":null,"tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        if s, ok := r.(string); ok && strings.Contains(s, \"unmarshal consume specs\") {\n            log.Fatalf(\"malformed SourceInputSpecs: %s\", s)\n        }\n        panic(r)\n    }\n}()","preventionTips":["Validate SourceInputSpecs JSON before deploying the function.","Ensure the function worker serializes ConsumerSpec values, never raw topic strings.","Add a round-trip json.Marshal/Unmarshal test for instance conf construction."],"tags":["go","json","configuration","panic","deserialization"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}