{"record":{"id":"b35fb343ec638b81","repo":"SigNoz/signoz","slug":"could-nt-generate-nil-check-for-fields-referenced","errorCode":null,"errorMessage":"could'nt generate nil check for fields referenced in value expr of add operator %s: %w","messagePattern":"could'nt generate nil check for fields referenced in value expr of add operator (.+?): %w","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"pkg/query-service/app/logparsingpipeline/pipelineBuilder.go","lineNumber":137,"sourceCode":"\t\t\t\t\t\t\"couldn't generate nil check for parseFrom of grok op %s: %w\", operator.Name, err,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\toperator.If = parseFromNotNilCheck\n\n\t\t\t} else if operator.Type == \"json_parser\" {\n\t\t\t\toperators, err := processJSONParser(&operator)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"couldn't process json_parser op %s: %s\", operator.Name, err)\n\t\t\t\t}\n\n\t\t\t\tfilteredOp = append(filteredOp, operators...)\n\t\t\t\tcontinue // Continue here to skip deduplication of json_parser operator\n\t\t\t} else if operator.Type == \"add\" {\n\t\t\t\tif strings.HasPrefix(operator.Value, \"EXPR(\") && strings.HasSuffix(operator.Value, \")\") {\n\t\t\t\t\texpression := strings.TrimSuffix(strings.TrimPrefix(operator.Value, \"EXPR(\"), \")\")\n\t\t\t\t\tfieldsNotNilCheck, err := fieldsReferencedInExprNotNilCheck(expression)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn nil, fmt.Errorf(\n\t\t\t\t\t\t\t\"could'nt generate nil check for fields referenced in value expr of add operator %s: %w\",\n\t\t\t\t\t\t\toperator.Name, err,\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\tif fieldsNotNilCheck != \"\" {\n\t\t\t\t\t\toperator.If = fieldsNotNilCheck\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if operator.Type == \"move\" || operator.Type == \"copy\" {\n\t\t\t\tfromNotNilCheck, err := fieldNotNilCheck(operator.From)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\n\t\t\t\t\t\t\"couldn't generate nil check for From field of %s op %s: %w\", operator.Type, operator.Name, err,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\toperator.If = fromNotNilCheck\n\t\t\t} else if operator.Type == \"remove\" {\n\t\t\t\tfieldNotNilCheck, err := fieldNotNilCheck(operator.Field)","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/SigNoz/signoz/blob/5069bf80b08f1f00d7e014eccc09902f9871004f/pkg/query-service/app/logparsingpipeline/pipelineBuilder.go#L119-L155","documentation":"For enabled add operators whose Value is an EXPRESSION — value of the form EXPR(...) — getOperators extracts the expression and runs fieldsReferencedInExprNotNilCheck to generate nil-guards for every referenced field. If that helper cannot resolve/guard the referenced fields (unknown field syntax, empty expression, parse failure), the builder fails with this wrapped error (note the typo 'could'nt' in the message — match on it exactly if you string-match).","triggerScenarios":"An add operator with value like EXPR(attributes.foo + attributes.bar) where the expression references fields the nil-check generator cannot handle, or an empty/malformed EXPR(). Applying the pipeline triggers the failure.","commonSituations":"Hand-written pipeline YAML with EXPR syntax errors; referencing nested/temporary fields not yet defined at that stage of the pipeline; version differences in the expression mini-language.","solutions":["Unwrap the error to see why fieldsReferencedInExprNotNilCheck failed.","Simplify the expression: reference only concrete attribute/resource fields (attributes.x, resource.y) that exist upstream.","Confirm the EXPR(...) wrapper is well-formed — non-empty body, balanced parentheses, no stray quotes.","Move complex logic into earlier operators (regex/json parsers) so the add expression only combines already-created fields."],"exampleFix":"// before\n- type: add\n  enabled: true\n  name: total\n  value: \"EXPR()\"  // empty expression\n\n// after\n- type: add\n  enabled: true\n  name: total\n  value: \"EXPR(attributes.price * attributes.qty)\"","handlingStrategy":"validation","validationCode":"func validExprValue(v string) bool {\n\tif !strings.HasPrefix(v, \"EXPR(\") { return true }\n\tinner := strings.TrimSuffix(strings.TrimPrefix(v, \"EXPR(\"), \")\")\n\treturn strings.TrimSpace(inner) != \"\"\n}\nif op.Type == \"add\" && op.Enabled && !validExprValue(op.Value) {\n\treturn fmt.Errorf(\"add operator %s has an empty EXPRESSION\", op.Name)\n}","typeGuard":"func isAddExprOpValid(op pipelinetypes.PipelineOperator) bool {\n\treturn op.Type != \"add\" || !op.Enabled || validExprValue(op.Value)\n}","tryCatchPattern":null,"preventionTips":["Lint EXPR(...) values for non-empty, balanced expressions and known field paths.","Only reference fields created by earlier operators in the same pipeline; document field ordering.","Use errors.Unwrap when diagnosing to reach the fieldsReferencedInExprNotNilCheck cause."],"tags":["log-pipelines","add-operator","expression","ottl","pipeline-builder"],"backgroundTag":"pipeline-operator-validation-failed","analyzedSha":"5069bf80b08f1f00d7e014eccc09902f9871004f","analyzedAt":"2026-08-28T06:22:12.824Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}