GoogleContainerTools/skaffold · info

%s. %s

Error message

%s. %s

What it means

Problem.AIError wraps a skaffold Problem (an error type carrying cause and description) and, if a Suggestion function is defined and returns entries, re-formats the error as '<problem text>. <suggestions>' using fmt.Errorf. It is not a failure of its own but the rendering step for actionable skaffold errors, invoked e.g. from isOldImageManifestProblem.

Source

Thrown at pkg/skaffold/errors/problem.go:70

		Err:         err,
	}
}

func (p Problem) Error() string {
	description := fmt.Sprintf("%s.", p.Err)
	if p.Description != nil {
		description = p.Description(p.Err)
	}
	return description
}

func (p Problem) AIError(i interface{}, err error) error {
	p.Err = err
	if p.Suggestion == nil {
		return p
	}
	if suggestions := p.Suggestion(i); len(suggestions) > 0 {
		return fmt.Errorf("%s. %s", strings.Trim(p.Error(), "."), concatSuggestions(suggestions))
	}
	return p
}

func isProblem(err error) (Problem, bool) {
	if p, ok := err.(Problem); ok {
		return p, true
	}
	return Problem{}, false
}

func AddPhaseProblems(phase constants.Phase, problems []Problem) {
	addPhaseProblemLock.Lock()
	if problemCatalog.allErrors == nil {
		problemCatalog = NewProblemCatalog()
	}
	problemCatalog.AddPhaseProblems(phase, problems)
	addPhaseProblemLock.Unlock()

View on GitHub (pinned to a1189de023)

Solutions

  1. If matching the error in tests or scripts, compare using errors.As against the skaffold Problem type instead of exact string equality
  2. Treat the suggestion suffix as advisory text, not part of the error identity
  3. Update golden-file test expectations to include the appended suggestion text

Example fix

// before
if err.Error() == "some known problem" { ... }
// after
var p sErrors.Problem
if errors.As(err, &p) && strings.Contains(p.Error(), "some known problem") { ... }
Defensive patterns

Strategy: type-guard

Type guard

func asProblem(err error) (sErrors.Problem, bool) {
    var p sErrors.Problem
    if errors.As(err, &p) {
        return p, true
    }
    return p, false
}

Try / catch

if err := run(); err != nil {
    var p sErrors.Problem
    if errors.As(err, &p) {
        log.Errorf("%s", p.Error()) // base problem text, suggestions stripped
    } else {
        return err
    }
}

Prevention

When it happens

Trigger: Any code path that converts a Problem into a user-facing error while the problem defines a Suggestion callback that returns at least one suggestion string; the returned error's message becomes '%s. %s' (problem error text trimmed of trailing dots, plus concatenated suggestions).

Common situations: Developers matching on the error string find the message now includes appended suggestions, breaking exact string comparison; older skaffold versions returned the plain Problem, so downstream string expectations changed between versions.


AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05). Data as JSON: /api/errors/847705ba519773d9. Report an issue: GitHub.