hashicorp/terraform · error
the string provided in credentials is neither valid json nor
Error message
the string provided in credentials is neither valid json nor a valid file path
What it means
Raised by the GCS backend when the 'credentials' string is not valid JSON and readPathOrContents did not treat it as a readable file path (no read error), so it is neither a JSON blob nor a loadable file. The backend refuses to pass garbage to the GCS client. This is the catch-all for a malformed credentials value.
Source
Thrown at internal/backend/remote-state/gcs/backend.go:204
} else {
creds = os.Getenv("GOOGLE_CREDENTIALS")
}
if tokenSource != nil {
credOptions = append(credOptions, option.WithTokenSource(tokenSource))
} else if creds != "" {
// to mirror how the provider works, we accept the file path or the contents
contents, err := readPathOrContents(creds)
if err != nil {
return backendbase.ErrorAsDiagnostics(
fmt.Errorf("Error loading credentials: %s", err),
)
}
if !json.Valid([]byte(contents)) {
return backendbase.ErrorAsDiagnostics(
fmt.Errorf("the string provided in credentials is neither valid json nor a valid file path"),
)
}
credOptions = append(credOptions, option.WithCredentialsJSON([]byte(contents)))
}
// Service Account Impersonation
if v := data.String("impersonate_service_account"); v != "" {
ServiceAccount := v
var delegates []string
delegatesVal := data.GetAttr("impersonate_service_account_delegates", cty.List(cty.String))
if !delegatesVal.IsNull() && delegatesVal.LengthInt() != 0 {
delegates = make([]string, 0, delegatesVal.LengthInt())
for it := delegatesVal.ElementIterator(); it.Next(); {
_, v := it.Element()
if v.IsNull() {
return backendbase.ErrorAsDiagnostics(View on GitHub (pinned to c9def3e214)
Solutions
- Provide the full service-account JSON key (download from GCP IAM > Service accounts > Keys) inline or via a readable file path.
- Validate the JSON before using: 'echo "$CREDENTIALS" | jq .' or 'python -m json.tool sa.json'.
- Avoid shell mangling: write the key to a file and reference the path, or export it via a heredoc.
- Confirm you are not passing the OAuth access_token, email, or project id in the 'credentials' field.
Example fix
# before: pasted email / mangled string -> 219
credentials = "tf-sa@my-project.iam.gserviceaccount.com"
# after: full service-account JSON
credentials = file("/abs/path/sa.json")
# validate first
jq empty /abs/path/sa.json && echo "valid json" Defensive patterns
Strategy: validation
Validate before calling
// Validate the credentials value is JSON or a path to JSON before init.
func validateCreds(creds string) error {
if json.Valid([]byte(creds)) { return nil }
b, err := os.ReadFile(creds)
if err != nil {
return fmt.Errorf("the string provided in credentials is neither valid json nor a valid file path")
}
if !json.Valid(b) {
return fmt.Errorf("credentials file %q is not valid JSON", creds)
}
return nil
} Prevention
- Provide the full service-account JSON key (inline or via file()).
- Validate with 'jq .' or 'python -m json.tool' before use.
- Do not paste the service-account email or a base64 blob into 'credentials'.
- Avoid shell mangling by storing the key in a file referenced by absolute path.
When it happens
Trigger: At backend.go:202-205: after readPathOrContents succeeds (returns a string), json.Valid([]byte(contents)) is false. Triggered when credentials is a non-JSON string that is also not an existing file path — e.g. a truncated key, a base64 blob, a service-account email, or pasted JSON with stray characters.
Common situations: Pasted the service-account email instead of the key JSON; pasted JSON that lost quotes/newlines through shell escaping; provided a base64-encoded key where raw JSON was expected; credentials file path was actually valid as a string but the file does not exist AND the string is not JSON (note: this fires when readPathOrContents returns the string unchanged because it is not a path).
Related errors
- Error loading credentials: %s
- can't set both encryption_key and kms_encryption_key
- storage.NewClient() failed: %v
- configuration file did not contain profile: %s
- unable to initialize the location client: %#v
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/b38cac87adc1faac.
Report an issue: GitHub.