🔧 Error Fixes
· 2 min read
Last updated on

Go: Multiple-Value in Single-Value Context — How to Fix It


You try to compile your Go code and the compiler says:

multiple-value os.Open() (untyped nil) in single-value context

Or more generally:

multiple-value someFunc() in single-value context

You’re calling a function that returns multiple values but only capturing one.

What causes this

In Go, functions commonly return multiple values — typically a result and an error. This is one of Go’s core patterns. Unlike languages where errors are thrown as exceptions, Go returns them as explicit values.

The compiler enforces that you handle all return values. You can’t just grab the first one and ignore the rest. This is by design — it forces you to deal with errors.

You’ll hit this when:

  • You assign a multi-return function to a single variable
  • You use a multi-return function directly in an expression (like passing it to fmt.Println as one argument)
  • You’re coming from a language like Python or JavaScript where you can ignore return values freely

Fix 1: Capture all return values

The standard fix — accept every value the function returns:

// ❌ os.Open returns (*File, error)
f := os.Open("config.json")

// ✅ Capture both values
f, err := os.Open("config.json")
if err != nil {
    log.Fatal(err)
}
defer f.Close()

This is the idiomatic Go pattern. Always check the error.

Fix 2: Discard a return value with the blank identifier

If you genuinely don’t need one of the return values, use _:

// ✅ Ignore the error (not recommended for I/O)
f, _ := os.Open("config.json")

// ✅ Ignore the value, keep the error
_, err := os.Open("config.json")
if err != nil {
    log.Fatal(err)
}

Use _ sparingly. Ignoring errors is a code smell in Go. It’s acceptable in cases like fmt.Fprintf where the error is rarely meaningful, but for file I/O, network calls, or database operations — always handle the error.

Fix 3: Handle it inline in an if statement

Go lets you combine the assignment and the error check in one line:

// ✅ Short variable declaration in if
if f, err := os.Open("config.json"); err != nil {
    log.Fatal(err)
} else {
    defer f.Close()
    // use f
}

Note that f and err are scoped to the if block in this pattern. If you need f outside the block, use the two-line version from Fix 1.

Fix 4: When using multi-return in function arguments

You can’t pass a multi-return function directly as an argument to another function that expects separate parameters:

// ❌ This won't compile
fmt.Println(strconv.Atoi("42"))

// ✅ Capture first, then pass
val, err := strconv.Atoi("42")
if err != nil {
    log.Fatal(err)
}
fmt.Println(val)

The one exception: you can pass a multi-return function to another function that accepts exactly those types as parameters. But this is rare and not worth relying on.

How to prevent it

  • Get comfortable with Go’s value, err := pattern — you’ll write it hundreds of times per project
  • Use a linter like errcheck or golangci-lint to catch ignored errors
  • If you find yourself ignoring errors frequently, reconsider your error handling strategy — wrapping errors with fmt.Errorf("context: %w", err) makes them more useful
  • IDE support (VS Code with gopls, GoLand) will highlight this error in real time before you even try to compile

Related: Go: Cannot Use X as Type Y — How to Fix It