{"record":{"id":"621b43e9aace9f60","repo":"gastownhall/beads","slug":"invalid-step-condition-format-q-expected-var","errorCode":null,"errorMessage":"invalid step condition format: %q (expected {{var}} or {{var}} == value)","messagePattern":"invalid step condition format: %q \\(expected (.+?)\\} or (.+?)\\} == value\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/formula/stepcondition.go","lineNumber":81,"sourceCode":"\tif m := stepCondComparePattern.FindStringSubmatch(condition); m != nil {\n\t\tvarName := m[1]\n\t\toperator := m[2]\n\t\texpected := strings.TrimSpace(m[3])\n\n\t\t// Remove quotes from expected value if present\n\t\texpected = unquoteValue(expected)\n\n\t\tactual := vars[varName]\n\n\t\tswitch operator {\n\t\tcase \"==\":\n\t\t\treturn actual == expected, nil\n\t\tcase \"!=\":\n\t\t\treturn actual != expected, nil\n\t\t}\n\t}\n\n\treturn false, fmt.Errorf(\"invalid step condition format: %q (expected {{var}} or {{var}} == value)\", condition)\n}\n\n// isTruthy returns true if a value is considered \"truthy\" for step conditions.\n// Falsy values: empty string, \"false\", \"0\", \"no\", \"off\"\n// All other values are truthy.\nfunc isTruthy(value string) bool {\n\tif value == \"\" {\n\t\treturn false\n\t}\n\tlower := strings.ToLower(value)\n\tswitch lower {\n\tcase \"false\", \"0\", \"no\", \"off\":\n\t\treturn false\n\t}\n\treturn true\n}\n\n// unquoteValue removes surrounding quotes from a value if present.","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/formula/stepcondition.go#L63-L99","documentation":"EvaluateStepCondition evaluates a Step.Condition string against supplied variables. Supported forms are `{{var}}` (truthiness) and comparisons like `{{var}} == value` / `!=`. Any condition string not matching these formats falls through to this error, unlike unmatched comparisons which return a bool.","triggerScenarios":"FilterStepsByCondition (directly or transitively) encounters a step whose Condition is neither `{{var}}` nor `{{var}} == value` / `{{var}} != value`: wrong braces, missing operand, unsupported operator (e.g. `>`), or malformed spacing.","commonSituations":"Formula authors write conditions using arbitrary expressions (`{{a}} && {{b}}`, `{{count}} >= 3`) assuming full expression support, or typo the template delimiters.","solutions":["Rewrite the condition to the supported form: `{{var}}`, `{{var}} == value`, or `{{var}} != value`.","Check exact syntax: double curly braces, no missing closing brace, operator surrounded by spaces.","Replace complex boolean conditions with multiple steps or pre-computed variables.","Inspect the failing step's `condition` field in the formula file and correct it."],"exampleFix":"// before\ncondition: \"{{count}} >= 3\"\n// after\ncondition: \"{{count}} == 3\"","handlingStrategy":"validation","validationCode":"func validCondition(c string) bool {\n    c = strings.TrimSpace(c)\n    if strings.HasPrefix(c, \"{{\") && strings.HasSuffix(c, \"}}\") && !strings.Contains(c[2:len(c)-2], \"}}\") {\n        inner := strings.TrimSpace(c[2 : len(c)-2])\n        if !strings.Contains(inner, \" \") { return true }\n        parts := strings.SplitN(inner, \" \", 2)\n        if len(parts) == 2 && strings.Count(parts[1], \" \") == 1 {\n            op := strings.Fields(parts[1])[0]\n            return op == \"==\" || op == \"!=\"\n        }\n    }\n    return false\n}","typeGuard":null,"tryCatchPattern":"if err := run(); err != nil && strings.Contains(err.Error(), \"invalid step condition format\") { /* surface condition string to the user for fixing */ }","preventionTips":["Restrict formula conditions to {{var}}, {{var}} == value, {{var}} != value.","Lint step conditions when parsing formula files, before execution.","Document that boolean operators (&&, ||, >=) are unsupported."],"tags":["formula","step-conditions","validation"],"backgroundTag":"invalid-condition-format","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}