golang/go · error

%s: malformed #cgo argument: %s

Error message

%s: malformed #cgo argument: %s

What it means

Failure in saveCgo while expanding ${SRCDIR} placeholders in each cgo argument via expandSrcDir. The function returns ok=false when a chunk fails safeCgoName (i.e. contains characters unsafe to pass to the C compiler's shell, such as an unmatched quote or a backslash path separator on Windows). The offending (post-expansion) argument is printed.

Source

Thrown at src/cmd/go/internal/modindex/build.go:473

			ok := false
			for _, c := range cond {
				if ctxt.matchAuto(c, nil) {
					ok = true
					break
				}
			}
			if !ok {
				continue
			}
		}

		args, err := splitQuoted(argstr)
		if err != nil {
			return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig)
		}
		for i, arg := range args {
			if arg, ok = expandSrcDir(arg, di.Dir); !ok {
				return fmt.Errorf("%s: malformed #cgo argument: %s", filename, arg)
			}
			args[i] = arg
		}

		switch verb {
		case "CFLAGS", "CPPFLAGS", "CXXFLAGS", "FFLAGS", "LDFLAGS":
			// Change relative paths to absolute.
			ctxt.makePathsAbsolute(args, di.Dir)
		}

		switch verb {
		case "CFLAGS":
			di.CgoCFLAGS = append(di.CgoCFLAGS, args...)
		case "CPPFLAGS":
			di.CgoCPPFLAGS = append(di.CgoCPPFLAGS, args...)
		case "CXXFLAGS":
			di.CgoCXXFLAGS = append(di.CgoCXXFLAGS, args...)
		case "FFLAGS":

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Convert all backslashes in cgo paths to forward slashes (`/`).
  2. Wrap ${SRCDIR} cleanly: `-I${SRCDIR}/include` with no stray quotes or shell metacharacters.
  3. Avoid shell operators (|, &, $ outside ${SRCDIR}, ;) in cgo arguments — they are passed verbatim.

Example fix

// before
// #cgo CFLAGS: -I${SRCDIR}\include
// after
// #cgo CFLAGS: -I${SRCDIR}/include
Defensive patterns

Strategy: validation

Validate before calling

// Replicate safeCgoName's spirit: reject shell-unsafe chars in cgo args that contain ${SRCDIR}.
var safeCgoRe = regexp.MustCompile(`^[A-Za-z0-9_./+@%-]*$`)

func lintCgoSrcDir(arg string) error {
    if !strings.Contains(arg, "${SRCDIR}") {
        return nil
    }
    for _, chunk := range strings.Split(arg, "${SRCDIR}") {
        if chunk != "" && !safeCgoRe.MatchString(chunk) {
            return fmt.Errorf("unsafe chars around ${SRCDIR}: %q", arg)
        }
    }
    return nil
}

Prevention

When it happens

Trigger: A cgo argument containing ${SRCDIR} where the surrounding text is unsafe for the shell, or an argument with a Windows-style backslash path that safeCgoName rejects. Reached when expandSrcDir returns ok=false.

Common situations: Hard-coding Windows paths like `#cgo CFLAGS: -I${SRCDIR}\include`; mixing backslashes with ${SRCDIR}; embedding shell metacharacters in a cgo flag.

Understand the failure class

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/056bf5426901d797. Report an issue: GitHub.