github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/states/statefile/diagnostics.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package statefile 5 6 import ( 7 "encoding/json" 8 "fmt" 9 10 "github.com/terramate-io/tf/tfdiags" 11 ) 12 13 const invalidFormat = "Invalid state file format" 14 15 // jsonUnmarshalDiags is a helper that translates errors returned from 16 // json.Unmarshal into hopefully-more-helpful diagnostics messages. 17 func jsonUnmarshalDiags(err error) tfdiags.Diagnostics { 18 var diags tfdiags.Diagnostics 19 if err == nil { 20 return diags 21 } 22 23 switch tErr := err.(type) { 24 case *json.SyntaxError: 25 // We've usually already successfully parsed a source file as JSON at 26 // least once before we'd use jsonUnmarshalDiags with it (to sniff 27 // the version number) so this particular error should not appear much 28 // in practice. 29 diags = diags.Append(tfdiags.Sourceless( 30 tfdiags.Error, 31 invalidFormat, 32 fmt.Sprintf("The state file could not be parsed as JSON: syntax error at byte offset %d.", tErr.Offset), 33 )) 34 case *json.UnmarshalTypeError: 35 // This is likely to be the most common area, describing a 36 // non-conformance between the file and the expected file format 37 // at a semantic level. 38 if tErr.Field != "" { 39 diags = diags.Append(tfdiags.Sourceless( 40 tfdiags.Error, 41 invalidFormat, 42 fmt.Sprintf("The state file field %q has invalid value %s", tErr.Field, tErr.Value), 43 )) 44 break 45 } else { 46 // Without a field name, we can't really say anything helpful. 47 diags = diags.Append(tfdiags.Sourceless( 48 tfdiags.Error, 49 invalidFormat, 50 "The state file does not conform to the expected JSON data structure.", 51 )) 52 } 53 default: 54 // Fallback for all other types of errors. This can happen only for 55 // custom UnmarshalJSON implementations, so should be encountered 56 // only rarely. 57 diags = diags.Append(tfdiags.Sourceless( 58 tfdiags.Error, 59 invalidFormat, 60 fmt.Sprintf("The state file does not conform to the expected JSON data structure: %s.", err.Error()), 61 )) 62 } 63 64 return diags 65 }