vitessio/vitess · error
bad literal argument
Error message
bad literal argument
What it means
astfmtgen's rewriteAstPrintf rewrites fmt-style calls in generated code; it assumes the format argument is a quoted string literal (ast.BasicLit) so it can parse the format directives. If strconv.Unquote fails, the second argument was not a valid string literal and the tool panics. This is a developer-time code-generation tool, so panicking is intentional fail-fast behavior.
Source
Thrown at go/tools/astfmtgen/main.go:169
}
func (r *Rewriter) rewriteLiteral(rcv ast.Expr, method string, arg ast.Expr) ast.Stmt {
expr := &ast.CallExpr{
Fun: &ast.SelectorExpr{
X: rcv,
Sel: &ast.Ident{Name: method},
},
Args: []ast.Expr{arg},
}
return &ast.ExprStmt{X: expr}
}
func (r *Rewriter) rewriteAstPrintf(cursor *astutil.Cursor, expr *ast.CallExpr) bool {
callexpr := expr.Fun.(*ast.SelectorExpr)
lit := expr.Args[1].(*ast.BasicLit)
format, err := strconv.Unquote(lit.Value)
if err != nil {
panic("bad literal argument")
}
end := len(format)
fieldnum := 0
for i := 0; i < end; {
lasti := i
for i < end && format[i] != '%' {
i++
}
if i > lasti {
var arg ast.Expr
var method string
lit := format[lasti:i]
if len(lit) == 1 {
method = "WriteByte"
arg = &ast.BasicLit{
Kind: gotoken.CHAR,View on GitHub (pinned to 01a25a7d17)
Solutions
- Make the format argument a plain string literal, e.g. ast_sprintf(node, "foo %n bar", xs).
- Check argument order so the format literal is the second argument.
- If the format must be dynamic, hoist the formatting out of the rewritten call or extend the tool to handle it.
Example fix
// before ast_sprintf(expr, formatString, args) // panics: bad literal argument // after ast_sprintf(expr, "expected format %n", args)
Defensive patterns
Strategy: validation
Validate before calling
// ensure the format arg of an ast_printf/ast_sprintf call is a quoted string literal
sel, ok := call.Args[1].(*ast.BasicLit)
if !ok || sel.Kind != token.STRING {
return fmt.Errorf("format must be a string literal, got %T", call.Args[1])
} Prevention
- Always pass literal format strings to ast_printf/ast_sprintf calls.
- Run `go generate` locally before committing generated-code changes.
- Keep the format literal in the fixed second-argument position.
When it happens
Trigger: Running go generate / astfmtgen against a printf-style call whose second argument is a non-literal string (a variable, concatenation, backtick oddity, or wrong argument position).
Common situations: Changing ast_printf/ast_sprintf calls to use a computed format string; reordering arguments so the literal is no longer Args[1]; introducing malformed quoting in the format string.
Related errors
- '%n' directive requires a slice
- slow path for `n` directive for slice of type other than Exp
- package '%s' does not contain 'ast_format.go'
- generator failed for type %s: %w
- unsupported pointer type %T
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/ba0722401d709c43.
Report an issue: GitHub.