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

  1. Make the format argument a plain string literal, e.g. ast_sprintf(node, "foo %n bar", xs).
  2. Check argument order so the format literal is the second argument.
  3. 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

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


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/ba0722401d709c43. Report an issue: GitHub.