Skip to content

[syntax-error-quality] Daily Syntax Error Quality Check: 2026-03-12 – Average Score 62.7/100 ⚠️ Below Threshold #20711

Description

@github-actions

📊 Error Message Quality Analysis

Analysis Date: 2026-03-12
Test Cases: 3
Average Score: 62.7/100
Status: ⚠️ Needs Improvement (below threshold of 70)


Executive Summary

Static analysis of the gh-aw compiler's error message quality across three error categories reveals an average score of 62.7/100, below the quality threshold of 70. One test case (YAML syntax errors) scored 44/100, breaching the critical threshold of 55. While the engine name validation error messages are excellent (80/100), YAML syntax errors suffer from wrong line positions, technical jargon, message duplication, and no corrective guidance. Schema validation errors for unknown properties are acceptable but lack examples or valid-value lists.

Key Findings:

  • Strengths: Engine validation errors have excellent "Did you mean" + example + docs link; schema errors show accurate source context with visual pointers
  • Weaknesses: YAML errors always report 1:1 for position (wrong); no corrective hints or examples for YAML and schema errors; Hint field in CompilerError struct is never rendered by FormatError()
  • Critical Issues: YAML frontmatter syntax errors produce confusing output: wrong outer line number, technical YAML parser jargon, and duplicated error message content due to fmt.Errorf("%s: %w", formattedErr, cause) chaining

Test Case Results

Test Case 1: Invalid YAML Syntax (workflow-generator.md) – Score: 44/100 ❌

Test Configuration

Workflow: .github/workflows/workflow-generator.md (112 lines, simple)
Error Type: Category A – Invalid YAML syntax
Error Introduced: Line 14: engine copilot (missing colon – should be engine: copilot)

Compiler Output (reconstructed from source analysis)

The error flows through:

  1. pkg/parser/frontmatter_content.go:68 – goccy YAML error wrapped as "failed to parse frontmatter:\n[14:8]: mapping value is not allowed in this context\n > 14 | engine copilot\n ^"
  2. pkg/workflow/compiler.go:84 – wrapped via formatCompilerError(markdownPath, "error", err.Error(), err) with hardcoded Line:1, Column:1
  3. pkg/workflow/compiler_error_formatter.go:32 – cause chained as fmt.Errorf("%s: %w", formattedErr, cause) → duplicates the error text
workflow-generator.md:1:1: error: failed to parse frontmatter:
[14:8]: mapping value is not allowed in this context
    12 |   contents: read
    13 |   issues: read
  > 14 | engine copilot
            ^
    15 |   pull-requests: read
: failed to parse frontmatter:
[14:8]: mapping value is not allowed in this context   ← DUPLICATED
    ...
```

#### Evaluation Scores

| Dimension | Score | Rating |
|-----------|-------|--------|
| Clarity | 14/25 | Poor |
| Actionability | 8/25 | Poor |
| Context | 13/20 | Acceptable |
| Examples | 2/15 | Critical |
| Consistency | 7/15 | Poor |
| **Total** | **44/100** | **❌ Critical** |

#### Strengths
- ✅ goccy YAML error includes correct inner line number and source context with `^` pointer
- ✅ Shows problematic source line

#### Weaknesses
- ❌ Outer position is always `file:1:1` (incorrect – error is at line 14)
- ❌ Technical YAML jargon: "mapping value is not allowed in this context" – confusing to non-YAML experts
- ❌ Error message is duplicated due to `fmt.Errorf("%s: %w", formattedErr, cause)` wrapping in `compiler_error_formatter.go:32`
- ❌ Two conflicting formats in the same output: outer `file:1:1:` + inner `[14:8]:`
- ❌ No suggestion or example of correct syntax

#### Improvement Suggestions

1. **Extract accurate line/col from the goccy YAML error before wrapping**:
   ```go
   // In compiler.go, instead of:
   return formatCompilerError(markdownPath, "error", err.Error(), err)
   // Use position extracted from the YAML error:
   line, col := extractPositionFromYAMLError(err)
   return formatCompilerErrorWithPosition(markdownPath, line, col, "error", err.Error(), nil)
   ```

2. **Prevent message duplication** – pass `nil` as cause when the message already includes the error:
   ```go
   // compiler_error_formatter.go line 32: Only chain cause when it adds NEW information
   // Currently duplicates content since message = err.Error()
   ```

3. **Translate common YAML errors to plain language** in `pkg/parser/yaml_error.go`:
   - `"mapping value is not allowed in this context"` → `"Missing ':' after key (e.g., 'engine copilot' should be 'engine: copilot')"`
   - `"did not find expected key"` → `"Incorrect indentation or missing key"`

4. **Add corrective example for missing colon errors**:
   ```
   Correct syntax:
   engine: copilot
   ```

</details>

<details>
<summary><b>Test Case 2: Invalid Engine Name (cli-version-checker.md)</b> – Score: 80/100 ✅</summary>

#### Test Configuration

**Workflow**: `.github/workflows/cli-version-checker.md` (342 lines, medium)  
**Error Type**: Category B – Invalid engine name  
**Error Introduced**: `engine: copiilot` (typo – double 'i', should be `copilot`)

#### Compiler Output (reconstructed from source analysis)

Source: `pkg/workflow/engine_validation.go:235` via `validateEngine("copiilot")`

```
cli-version-checker.md:1:1: error: invalid engine: copiilot. Valid engines are: claude, codex, copilot.

Did you mean: copilot?

Example:
engine: copilot

See: https://github.com/github/gh-aw/blob/main/docs/src/content/docs/reference/engines.md
```

#### Evaluation Scores

| Dimension | Score | Rating |
|-----------|-------|--------|
| Clarity | 22/25 | Excellent |
| Actionability | 22/25 | Excellent |
| Context | 11/20 | Acceptable |
| Examples | 13/15 | Excellent |
| Consistency | 12/15 | Good |
| **Total** | **80/100** | **✅ Good** |

#### Strengths
- ✅ Lists all valid engines in the error message
- ✅ "Did you mean: copilot?" via Levenshtein distance fuzzy matching
- ✅ Shows correct usage example: `engine: copilot`
- ✅ Links to documentation

#### Weaknesses
- ⚠️ Position is always `file:1:1` (the engine field is not at line 1 – should detect actual line)
- ⚠️ No source code context shown (no `Context` field populated)

#### Improvement Suggestions

1. **Populate source context** – read the source file and add surrounding lines to show where `engine: copiilot` appears
2. **Use accurate line position** – detect the line where `engine:` is defined in the frontmatter

</details>

<details>
<summary><b>Test Case 3: Invalid Permissions Scope (pr-triage-agent.md)</b> – Score: 64/100 ⚠️</summary>

#### Test Configuration

**Workflow**: `.github/workflows/pr-triage-agent.md` (450 lines, complex)  
**Error Type**: Category C – Invalid configuration field  
**Error Introduced**: `permissions: { unknown-scope: read }` (invalid permission scope)

#### Compiler Output (reconstructed from source analysis)

Source: `pkg/parser/schema_errors.go:223` → `rewriteAdditionalPropertiesError()` → `formatCompilerErrorWithPosition()`

```
pr-triage-agent.md:4:3: error: Unknown property: unknown-scope
   2 | permissions:
 > 3 |   unknown-scope: read
     |   ^^^^^^^^^^^^^
   4 | ---

Evaluation Scores

Dimension Score Rating
Clarity 21/25 Excellent
Actionability 10/25 Poor
Context 17/20 Excellent
Examples 3/15 Critical
Consistency 13/15 Good
Total 64/100 ⚠️ Acceptable

Strengths

  • ✅ Accurate file:line:col position
  • ✅ Source code context with visual pointer (^^^^^)
  • ✅ Clear "Unknown property" wording

Weaknesses

  • ❌ No list of valid permission scopes (contents, issues, pull-requests, etc.)
  • ❌ Hints intentionally removed (// Hints removed as per requirements in schema_compiler.go)
  • ❌ No example of valid permissions configuration
  • ❌ User left with no guidance on what valid values are

Improvement Suggestions

  1. List valid values for known enumerations – for permissions, enumerate valid scopes:

    Unknown property: unknown-scope.
    Valid permission scopes: actions, attestations, checks, contents, deployments,
    discussions, id-token, issues, packages, pages, pull-requests, security-events,
    statuses, workflows.
    ```
    
    
  2. Re-evaluate the "hints removed" policy – at minimum, add valid-value lists without free-form hints

  3. Add a compact example:

    Example:
    permissions:
      contents: read
      issues: write
    

Overall Statistics

Metric Value
Tests Run 3
Average Score 62.7/100
Excellent (85+) 0
Good (70-84) 1 (Test 2: engine name)
Acceptable (55-69) 1 (Test 3: permissions)
Poor / Critical (<55) 1 (Test 1: YAML syntax)

Quality Assessment: ❌ Needs Improvement (Average 62.7/100, below threshold of 70; Test Case 1 breaches critical threshold of 55)


Priority Improvement Recommendations

🔴 High Priority

1. Fix wrong line:col in formatCompilerError fallback path

All errors routed through formatCompilerError() in compiler_error_formatter.go hardcode Line: 1, Column: 1. This affects YAML syntax errors, engine validation, and many others.

  • File: pkg/workflow/compiler.go + pkg/workflow/compiler_error_formatter.go
  • Fix: Extract position from the underlying error before falling back to 1:1; or at minimum pass 0 to suppress the misleading position
  • Impact: Fixes misleading file:1:1 that causes IDE integrations to jump to wrong location

2. Fix YAML error message duplication

In pkg/workflow/compiler_error_formatter.go:32:

// CURRENT (causes duplication when message = err.Error()):
return fmt.Errorf("%s: %w", formattedErr, cause)

// SUGGESTED FIX – only chain when cause adds new information:
if cause != nil && cause.Error() != message {
    return fmt.Errorf("%s: %w", formattedErr, cause)
}
return errors.New(formattedErr)

3. Translate YAML parser jargon to plain English

In pkg/parser/yaml_error.go, add a translation layer for common goccy/go-yaml error patterns:

var yamlErrorTranslations = []struct {
    pattern     string
    replacement string
}{
    {"mapping value is not allowed in this context", "unexpected value – did you forget a ':' after a key?"},
    {"did not find expected key",                    "incorrect indentation or missing key name"},
    {"could not find expected ':'",                  "missing ':' between key and value"},
    {"found character that cannot start any token",  "invalid character – check indentation uses spaces, not tabs"},
}

🟡 Medium Priority

4. Implement Hint field rendering in FormatError()

The Hint field is defined in console.CompilerError but never rendered by FormatError() in pkg/console/console.go. This means any code that sets Hint silently discards the hint.

// Add after context rendering in FormatError() (pkg/console/console.go ~line 74):
if err.Hint != "" {
    output.WriteString(applyStyle(styles.Info, "hint: "))
    output.WriteString(err.Hint)
    output.WriteString("\n")
}

5. Add valid-values lists to schema validation errors for known enumerations

In pkg/parser/schema_errors.go, when an additionalProperties error occurs on a well-known field like permissions, append the valid values:

var knownFieldValidValues = map[string]string{
    "permissions": "Valid scopes: actions, contents, issues, pull-requests, ...",
    "engine":      "Valid values: copilot, claude, codex (see engine validation)",
}

🟢 Low Priority

6. Add source context to engine/semantic validation errors

Engine validation errors and other semantic errors use formatCompilerError() which doesn't populate Context (source lines). Reading the source file to extract the relevant lines would improve these messages:

// After reading the workflow file, extract context lines and pass to console.CompilerError
context, line, col := extractContextFromSource(markdownPath, "engine:")

Implementation Guide

Files to Modify

File Change
pkg/console/console.go Add Hint field rendering in FormatError() after context block
pkg/workflow/compiler_error_formatter.go Fix duplication: don't chain cause when message == cause.Error()
pkg/workflow/compiler.go Extract actual line/col from YAML errors before calling formatCompilerError
pkg/parser/yaml_error.go Add YAML jargon translation map + apply before returning formatted error
pkg/parser/schema_errors.go Append valid-value hints for known field enumerations

Success Metrics

  1. YAML syntax errors: Outer file:line:col matches actual error line (not 1:1)
  2. YAML syntax errors: Message appears once (no duplication)
  3. Schema errors: Valid-value lists included for permission scopes and other enumerations
  4. All errors: Hint field is rendered when set
  5. Average quality score: ≥ 70/100 on next daily check

References:

Generated by Daily Syntax Error Quality Check workflow
Next check: Runs daily

Generated by Daily Syntax Error Quality Check · ◷

  • expires on Mar 15, 2026, 6:23 PM UTC

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions