Skip to content

Fix engine validation error location and improve error detection (#issue)#21023

Merged
pelikhan merged 3 commits intomainfrom
copilot/fix-yaml-error-message-location
Mar 15, 2026
Merged

Fix engine validation error location and improve error detection (#issue)#21023
pelikhan merged 3 commits intomainfrom
copilot/fix-yaml-error-message-location

Conversation

Copy link
Contributor

Copilot AI commented Mar 15, 2026

Summary

Fixes the medium-priority item from the syntax error quality issue: engine validation errors now include a file:line:col: prefix pointing to the engine: field in the source file, instead of showing no file location at all.

Problem

When compiling a workflow with an invalid engine (e.g., engine: openai_gpt), the error had no file location:

invalid engine: openai_gpt. Valid engines are: claude, codex, copilot, gemini.

Example:
engine: copilot

See: https://...

The root cause: compile_workflow_processor.go calls ParseWorkflowFile directly (bypassing CompileWorkflow), so unformatted errors from engine catalog resolution were never wrapped with file location.

Changes

pkg/workflow/compiler_error_formatter.go

  • formatCompilerError and formatCompilerErrorWithPosition now always return *wrappedCompilerError (even when cause == nil), enabling reliable type-based detection
  • Added isFormattedCompilerError(err) helper using errors.As — replaces the previous fragile strings.Contains(err.Error(), "error:") check

pkg/workflow/compiler.go

  • Replaced fragile string-contains check with isFormattedCompilerError(err)

pkg/workflow/compiler_orchestrator_workflow.go

  • Engine errors from setupEngineAndImports and processToolsAndMarkdown now get wrapped with proper file location
  • Uses findFrontmatterFieldLine to pinpoint the exact engine: line for accurate file:line:col: navigation

pkg/workflow/frontmatter_error.go

  • Added findFrontmatterFieldLine helper: scans frontmatter lines for a top-level key and returns its 1-based document line number (0 if not found)

Tests

  • compiler_yaml_test.go: added TestEngineValidationErrorHasFileLocation — verifies that invalid engine errors include the correct file:line:col: prefix
  • compiler_error_formatter_test.go: unit tests for isFormattedCompilerError
  • frontmatter_error_test.go: unit tests for findFrontmatterFieldLine (including edge cases: absent field, indented keys, prefix collisions)

After Fix

/tmp/test-engine-typo4.md:3:1: error: invalid engine: openai_gpt. Valid engines are: claude, codex, copilot, gemini.

Example:
engine: copilot

See: https://...

Security Summary

No security vulnerabilities were introduced or discovered. The changes are purely error-message formatting improvements with no user-controlled input parsing or external interactions.

Copilot AI and others added 3 commits March 15, 2026 03:34
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Improves workflow compilation diagnostics so invalid engine: values report a precise file:line:col: location, and replaces fragile string-based “already formatted” detection with type-based detection.

Changes:

  • Wraps engine-related errors from ParseWorkflowFile with a source location pointing to the engine: frontmatter line (when available).
  • Makes compiler error formatting consistently return *wrappedCompilerError and adds isFormattedCompilerError(err) using errors.As.
  • Adds unit/integration tests for findFrontmatterFieldLine, isFormattedCompilerError, and engine validation error location formatting.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
pkg/workflow/compiler_orchestrator_workflow.go Wraps unformatted engine/setup and tools/markdown errors; attempts to pinpoint engine: line for navigation.
pkg/workflow/compiler.go Switches from string-contains formatting detection to isFormattedCompilerError.
pkg/workflow/compiler_error_formatter.go Always returns *wrappedCompilerError; adds isFormattedCompilerError helper using errors.As.
pkg/workflow/frontmatter_error.go Adds findFrontmatterFieldLine helper to locate a top-level frontmatter key line.
pkg/workflow/compiler_yaml_test.go Adds test ensuring invalid engine errors include correct file:line:col: prefix.
pkg/workflow/compiler_error_formatter_test.go Adds tests for isFormattedCompilerError.
pkg/workflow/frontmatter_error_test.go Adds tests for findFrontmatterFieldLine edge cases.
Comments suppressed due to low confidence (1)

pkg/workflow/frontmatter_error.go:69

  • The docstring says “first non-space key matches fieldName”, but the implementation intentionally only matches non-indented lines (strings.HasPrefix(line, fieldName+":")) and will not match keys with leading whitespace. Please adjust the wording to reflect the actual behavior (e.g., “matches lines that start with fieldName: with no leading whitespace”).
// findFrontmatterFieldLine searches frontmatterLines for a line whose first
// non-space key matches fieldName (e.g., "engine") and returns the 1-based
// document line number.  frontmatterStart is the 1-based line number of the
// first frontmatter line (i.e., the line immediately after the opening "---").
// Returns 0 if the field is not found.
//
// Only top-level (non-indented) keys are matched.  Nested values that happen
// to contain the field name are ignored.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +71 to +75
prefix := fieldName + ":"
for i, line := range frontmatterLines {
// Match only non-indented lines so nested YAML values are not confused
// with top-level keys (e.g. " engine: ..." inside a mapping is ignored).
if strings.HasPrefix(line, prefix) {
Comment on lines +42 to +45
name: "fmt.Errorf error is not formatted",
err: errors.New("wrapped: plain error"),
expected: false,
},
Comment on lines +41 to +53
// Wrap unformatted errors with file location. Errors produced by
// formatCompilerError/formatCompilerErrorWithPosition are already
// console-formatted and must not be double-wrapped.
if isFormattedCompilerError(err) {
return nil, err
}
// Try to point at the exact line of the "engine:" field so the user can
// navigate directly to the problem location.
engineLine := findFrontmatterFieldLine(result.FrontmatterLines, result.FrontmatterStart, "engine")
if engineLine > 0 {
return nil, formatCompilerErrorWithPosition(cleanPath, engineLine, 1, "error", err.Error(), err)
}
return nil, formatCompilerError(cleanPath, "error", err.Error(), err)
Comment on lines +78 to 84
// ParseWorkflowFile already returns formatted compiler errors; pass them through.
if isFormattedCompilerError(err) {
return err
}
// Otherwise, create a basic formatted error with wrapping
// Fallback for any unformatted error that slipped through.
return formatCompilerError(markdownPath, "error", err.Error(), err)
}
Comment on lines +48 to 54
// isFormattedCompilerError reports whether err is already a console-formatted compiler error
// produced by formatCompilerError or formatCompilerErrorWithPosition. Use this instead of
// fragile string-contains checks to avoid double-wrapping.
func isFormattedCompilerError(err error) bool {
var wce *wrappedCompilerError
return errors.As(err, &wce)
}
@pelikhan
Copy link
Contributor

@copilot review comments

@pelikhan pelikhan merged commit 608d81d into main Mar 15, 2026
92 of 93 checks passed
@pelikhan pelikhan deleted the copilot/fix-yaml-error-message-location branch March 15, 2026 04:30
Copilot stopped work on behalf of pelikhan due to an error March 15, 2026 04:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[syntax-error-quality] Syntax error messages need improvements — YAML errors show misleading location and jargon

3 participants