lima-vm/lima · error

failed to unmarshal line %#q: %w

Error message

failed to unmarshal line %#q: %w

What it means

readKubectlStream parses newline-delimited kubectl JSON watch output. Each line must be a JSON object with `type` and `object` fields. When a line is not valid JSON (truncated output, mixed non-JSON text like kubectl warnings, encoding corruption), this error is thrown with the offending line quoted.

Source

Thrown at pkg/guestagent/kubernetesservice/kubernetesservice.go:168

	scanner := bufio.NewScanner(r)
	// increase buffer in case of large JSON objects
	const maxBuf = 10 * units.MiB
	buf := make([]byte, 0, 64*units.KiB)
	scanner.Buffer(buf, maxBuf)

	for scanner.Scan() {
		line := scanner.Bytes()
		line = bytes.TrimSpace(line)
		if len(line) == 0 {
			continue
		}

		var ev struct {
			Type   eventType       `json:"type"`
			Object json.RawMessage `json:"object"`
		}
		if err := json.Unmarshal(line, &ev); err != nil {
			return fmt.Errorf("failed to unmarshal line %#q: %w", string(line), err)
		}

		var svc service
		if err := json.Unmarshal(ev.Object, &svc); err != nil {
			return fmt.Errorf("failed to unmarshal service object: %w (line=%#q)", err, line)
		}

		key := svc.Metadata.Namespace + "/" + svc.Metadata.Name
		s.rwMutex.Lock()
		switch ev.Type {
		case added, modified:
			s.serviceSpecs[key] = &svc.Spec
		case deleted:
			delete(s.serviceSpecs, key)
		default:
			// NOP
		}
		s.rwMutex.Unlock()

View on GitHub (pinned to dd909d0973)

Solutions

  1. Inspect the quoted line in the error; if it is a kubectl warning, run with `--warnings-as-errors=false` isolation or use `--output-watch-events`/stable flag combinations.
  2. Ensure kubectl is invoked with `-o json` and a version supporting JSON watch output.
  3. Filter or skip non-JSON lines before unmarshaling if robustness is needed.
  4. Retry the watch if the stream was truncated by a transient kill.

Example fix

// before: any garbage line aborts the whole stream
if err := json.Unmarshal(line, &ev); err != nil {
	return fmt.Errorf("failed to unmarshal line %#q: %w", string(line), err)
}
// after: skip lines that are not JSON watch events
if err := json.Unmarshal(line, &ev); err != nil {
	logrus.Debugf("skipping non-JSON line: %s", line)
	continue
}
Defensive patterns

Strategy: validation

Validate before calling

// skip lines that are not JSON objects before unmarshaling
trimmed := bytes.TrimSpace(line)
if len(trimmed) == 0 || trimmed[0] != '{' {
	return nil // skip non-JSON kubectl output
}

Try / catch

if err := readKubectlStream(stdout); err != nil {
	if strings.Contains(err.Error(), "failed to unmarshal line") {
		log.WithError(err).Warn("skipping malformed kubectl output line")
		return nil
	}
	return err
}

Prevention

When it happens

Trigger: startAndStreamKubectl -> readKubectlStream when scanner yields a line that json.Unmarshal cannot decode into the anonymous {type, object} struct.

Common situations: kubectl emits plain-text warnings or error banners (e.g. 'Unable to connect') interleaved with the JSON stream; a line is truncated due to buffering or signal kill; locale/encoding issues corrupt output.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of lima-vm/lima@dd909d0973 (2026-09-01). Data as JSON: /api/errors/aac742c8e07f193f. Report an issue: GitHub.