{"record":{"id":"8a9c2beefafd0d4c","repo":"nektos/act","slug":"unclosed-brackets-the-following-format-string-is","errorCode":null,"errorMessage":"Unclosed brackets. The following format string is invalid: '%s'","messagePattern":"Unclosed brackets\\. The following format string is invalid: '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/exprparser/functions.go","lineNumber":130,"sourceCode":"\t\t\t}\n\n\t\tcase bracketClose: // found }\n\t\t\tswitch character {\n\t\t\tcase '}':\n\t\t\t\toutput += \"}\"\n\t\t\t\treplacementIndex = \"\"\n\t\t\t\tstate = passThrough\n\n\t\t\tdefault:\n\t\t\t\tpanic(\"Invalid format parser state\")\n\t\t\t}\n\t\t}\n\t}\n\n\tif state != passThrough {\n\t\tswitch state {\n\t\tcase bracketOpen:\n\t\t\treturn \"\", fmt.Errorf(\"Unclosed brackets. The following format string is invalid: '%s'\", input)\n\n\t\tcase bracketClose:\n\t\t\treturn \"\", fmt.Errorf(\"Closing bracket without opening one. The following format string is invalid: '%s'\", input)\n\t\t}\n\t}\n\n\treturn output, nil\n}\n\nfunc (impl *interperterImpl) join(array reflect.Value, sep reflect.Value) (string, error) {\n\tseparator := impl.coerceToString(sep).String()\n\tswitch array.Kind() {\n\tcase reflect.Slice:\n\t\tvar items []string\n\t\tfor i := 0; i < array.Len(); i++ {\n\t\t\titems = append(items, impl.coerceToString(array.Index(i).Elem()).String())\n\t\t}\n","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/nektos/act/blob/4f411281417e88660bea1c1a1749aa71ae0bd60f/pkg/exprparser/functions.go#L112-L148","documentation":"Thrown by format() when the input ends while still inside a placeholder: an opening '{' was consumed (state bracketOpen) but no closing '}' arrived. The string is truncated after an unescaped brace.","triggerScenarios":"format('Hello {0') — missing closing brace; odd number of braces like format('{'); a brace intended literally that was not escaped as '{{'.","commonSituations":"Hand-editing long format strings; templates whose content contains JSON or CSS braces; typos when escaping braces (single '{' instead of '{{').","solutions":["Close every placeholder: format('Hello {0').","Escape literal braces with double braces '{{' '}}'.","Prefer string concatenation or toJSON for brace-heavy output instead of format()."],"exampleFix":"# before\n${{ format('value = {0', x) }}\n# after\n${{ format('value = {0}', x) }}","handlingStrategy":"validation","validationCode":"func balancedBraces(tpl string) bool {\n  depth := 0\n  for i := 0; i < len(tpl); i++ {\n    if tpl[i] == '{' && i+1 < len(tpl) && tpl[i+1] == '{' { i++; continue }\n    if tpl[i] == '}' && i+1 < len(tpl) && tpl[i+1] == '}' { i++; continue }\n    switch tpl[i] {\n    case '{': depth++\n    case '}': depth--\n    }\n    if depth < 0 || depth > 1 { return false }\n  }\n  return depth == 0\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Escape literal braces with {{ }}","Avoid brace-heavy text (JSON, CSS) inside format()","Use toJSON for structured output"],"tags":["expressions","format-function","workflow-yaml","unbalanced-braces"],"backgroundTag":null,"analyzedSha":"4f411281417e88660bea1c1a1749aa71ae0bd60f","analyzedAt":"2026-08-15T09:19:46.307Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}