diff --git a/pkg/parser/import_error.go b/pkg/parser/import_error.go index ad3e1edbe4..62e596aec5 100644 --- a/pkg/parser/import_error.go +++ b/pkg/parser/import_error.go @@ -84,6 +84,13 @@ type FormattedParserError struct { func (e *FormattedParserError) Error() string { return e.formatted } func (e *FormattedParserError) Unwrap() error { return e.cause } +// NewFormattedParserError creates a FormattedParserError with the given pre-formatted +// message string. Use this in external packages (e.g. pkg/workflow) to return an error +// that isFormattedCompilerError can detect without double-wrapping. +func NewFormattedParserError(formatted string) *FormattedParserError { + return &FormattedParserError{formatted: formatted} +} + // FormatImportError formats an import error as a compilation error with source location func FormatImportError(err *ImportError, yamlContent string) error { importErrorLog.Printf("Formatting import error: path=%s, file=%s, line=%d", err.ImportPath, err.FilePath, err.Line) diff --git a/pkg/parser/schema_compiler.go b/pkg/parser/schema_compiler.go index fb18aa7b04..96ced941de 100644 --- a/pkg/parser/schema_compiler.go +++ b/pkg/parser/schema_compiler.go @@ -354,7 +354,7 @@ func validateWithSchemaAndLocation(frontmatter map[string]any, schemaJSON, conte // Format and return the error formattedErr := console.FormatError(compilerErr) - return errors.New(formattedErr) + return &FormattedParserError{formatted: formattedErr} } } @@ -382,7 +382,7 @@ func validateWithSchemaAndLocation(frontmatter map[string]any, schemaJSON, conte // Format and return the error formattedErr := console.FormatError(compilerErr) - return errors.New(formattedErr) + return &FormattedParserError{formatted: formattedErr} } // Fallback to the original error if we can't format it nicely diff --git a/pkg/workflow/compiler_error_formatter_test.go b/pkg/workflow/compiler_error_formatter_test.go index d1277af54e..d631ee16da 100644 --- a/pkg/workflow/compiler_error_formatter_test.go +++ b/pkg/workflow/compiler_error_formatter_test.go @@ -45,6 +45,11 @@ func TestIsFormattedCompilerError(t *testing.T) { }, "imports:\n - missing.md"), expected: true, }, + { + name: "error from parser.NewFormattedParserError is detected as formatted", + err: parser.NewFormattedParserError("workflow.md:5:3: error: bad value"), + expected: true, + }, { name: "plain error is not formatted", err: errors.New("plain error"), diff --git a/pkg/workflow/frontmatter_error.go b/pkg/workflow/frontmatter_error.go index 2d90c92a35..076046d12b 100644 --- a/pkg/workflow/frontmatter_error.go +++ b/pkg/workflow/frontmatter_error.go @@ -73,11 +73,11 @@ func (c *Compiler) createFrontmatterError(filePath, content string, err error, f context := errorStr[loc[0]+1:] // +1 to skip the leading newline // Return VSCode-compatible format on first line, followed by source context only frontmatterErrorLog.Print("Formatting error for VSCode compatibility") - return fmt.Errorf("%s\n%s", vscodeFormat, context) + return parser.NewFormattedParserError(fmt.Sprintf("%s\n%s", vscodeFormat, context)) } // If we can't extract source context, return just the VSCode format - return fmt.Errorf("%s", vscodeFormat) + return parser.NewFormattedParserError(vscodeFormat) } // Fallback if we can't parse the line/col