Skip to content

Commit c110ef2

Browse files
authored
fix: Addressing nil Range and Snippet in SourceSnippets (#6731)
1 parent f0a519d commit c110ef2

3 files changed

Lines changed: 84 additions & 5 deletions

File tree

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
version: "v1.1.4"
3+
category: "bug-fixes"
4+
---
5+
6+
#### `hcl validate` no longer crashes on errors that carry no source location
7+
8+
`terragrunt hcl validate` crashed while formatting its output when one of the errors it found had no position in the configuration. Terragrunt now prints that error's summary and detail, without a location line.

internal/view/human_render.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,15 @@ func (render *HumanRender) Diagnostic(diag *diagnostic.Diagnostic) (string, erro
202202
}
203203

204204
func (render *HumanRender) SourceSnippets(diag *diagnostic.Diagnostic) (string, error) {
205-
if diag.Range == nil || diag.Snippet == nil {
206-
// This should generally not happen, as long as sources are always
207-
// loaded through the main loader. We may load things in other
208-
// ways in weird cases, so we'll tolerate it at the expense of
209-
// a not-so-helpful error message.
205+
// [diagnostic.NewDiagnostic] leaves Range nil for an HCL diagnostic that has no
206+
// Subject, meaning it points at no position in the configuration.
207+
if diag.Range == nil {
208+
return "", nil
209+
}
210+
211+
// [diagnostic.NewDiagnostic] fills Range and Snippet together, so only a
212+
// diagnostic built elsewhere reaches here with a position and no snippet.
213+
if diag.Snippet == nil {
210214
return fmt.Sprintf(
211215
" on %s line %d:\n (source code not available)\n",
212216
diag.Range.Filename,

internal/view/human_render_test.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package view_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/gruntwork-io/terragrunt/internal/view"
7+
"github.com/gruntwork-io/terragrunt/internal/view/diagnostic"
8+
"github.com/gruntwork-io/terragrunt/test/helpers/venvtest"
9+
"github.com/hashicorp/hcl/v2"
10+
"github.com/stretchr/testify/require"
11+
)
12+
13+
func TestHumanRenderDiagnosticsWithoutSourceCode(t *testing.T) {
14+
t.Parallel()
15+
16+
testCases := []struct {
17+
diag *diagnostic.Diagnostic
18+
name string
19+
expected string
20+
}{
21+
{
22+
name: "range and snippet missing",
23+
diag: &diagnostic.Diagnostic{
24+
Severity: diagnostic.DiagnosticSeverity(hcl.DiagError),
25+
Summary: "Failed to read configuration",
26+
Detail: "The file could not be opened.",
27+
},
28+
expected: "╷\n" +
29+
"│ Error: Failed to read configuration\n" +
30+
"│\n" +
31+
"│ The file could not be opened.\n" +
32+
"╵\n",
33+
},
34+
{
35+
name: "snippet missing",
36+
diag: &diagnostic.Diagnostic{
37+
Range: &diagnostic.Range{
38+
Filename: "terragrunt.hcl",
39+
Start: diagnostic.Pos{Line: 7, Column: 1, Byte: 42},
40+
End: diagnostic.Pos{Line: 7, Column: 9, Byte: 50},
41+
},
42+
Severity: diagnostic.DiagnosticSeverity(hcl.DiagError),
43+
Summary: "Unsupported block type",
44+
Detail: "Blocks of type \"foo\" are not expected here.",
45+
},
46+
expected: "╷\n" +
47+
"│ Error: Unsupported block type\n" +
48+
"│\n" +
49+
"│ on terragrunt.hcl line 7:\n" +
50+
"│ (source code not available)\n" +
51+
"│ Blocks of type \"foo\" are not expected here.\n" +
52+
"╵\n",
53+
},
54+
}
55+
56+
for _, tc := range testCases {
57+
t.Run(tc.name, func(t *testing.T) {
58+
t.Parallel()
59+
60+
render := view.NewHumanRender(venvtest.New(), true)
61+
62+
actual, err := render.Diagnostics(diagnostic.Diagnostics{tc.diag})
63+
require.NoError(t, err)
64+
require.Equal(t, tc.expected, actual)
65+
})
66+
}
67+
}

0 commit comments

Comments
 (0)