hashicorp/terraform · error

refresh Ecs sts token err, fail to get AccessKeyId

Error message

refresh Ecs sts token err, fail to get AccessKeyId: %s

What it means

Thrown while refreshing an ECS STS token after 'Code' was "Success": a JMESPath search for 'AccessKeyId' errored. Although the response was a Success object, the JMESPath traversal of the AccessKeyId path raised an error (not nil) — typically because the data shape changed between the Code lookup and the credential lookup, or the field is nested differently than expected.

Solutions

  1. Inspect the full metadata response body to see where AccessKeyId lives.
  2. Align the Alibaba Cloud SDK / backend version with the metadata-service contract in your region.
  3. Re-attach the RAM role to force a fresh, complete credential document.
  4. If a proxy is in play, disable it for the 100.100.100.200 endpoint to avoid truncated responses.
Defensive patterns

Strategy: validation

Validate before calling

// After metadata Success, verify AccessKeyId resolves as a non-nil string.
avid, ok := data.(map[string]interface{})["AccessKeyId"].(string)
if !ok || avid == "" {
    return fmt.Errorf("metadata missing AccessKeyId")
}

Type guard

func hasAccessKeyId(v interface{}) bool {
    m, ok := v.(map[string]interface{}); if !ok { return false }
    s, ok := m["AccessKeyId"].(string); return ok && s != ""
}

Prevention

When it happens

Trigger: The metadata JSON contains 'Code':'Success' but the structure around the credential fields is unexpected (e.g., credentials nested under an extra key, or the field is absent and JMESPath cannot resolve the path on the given structure).

Common situations: A new metadata-service version returns credentials nested under a 'Credentials' or 'SecurityToken' object while Code stays at top level; SDK/backend version mismatch; or a partial/truncated response body.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/dd5a5aa88c78ff3e. Report an issue: GitHub.

Appendix: source

Thrown at internal/backend/remote-state/oss/backend.go:690

	}
	var data interface{}
	err = json.Unmarshal(response.GetHttpContentBytes(), &data)
	if err != nil {
		err = fmt.Errorf("refresh Ecs sts token err, json.Unmarshal fail: %s", err.Error())
		return
	}
	code, err := jmespath.Search("Code", data)
	if err != nil {
		err = fmt.Errorf("refresh Ecs sts token err, fail to get Code: %s", err.Error())
		return
	}
	if code.(string) != "Success" {
		err = fmt.Errorf("refresh Ecs sts token err, Code is not Success")
		return
	}
	accessKeyId, err := jmespath.Search("AccessKeyId", data)
	if err != nil {
		err = fmt.Errorf("refresh Ecs sts token err, fail to get AccessKeyId: %s", err.Error())
		return
	}
	accessKeySecret, err := jmespath.Search("AccessKeySecret", data)
	if err != nil {
		err = fmt.Errorf("refresh Ecs sts token err, fail to get AccessKeySecret: %s", err.Error())
		return
	}
	securityToken, err := jmespath.Search("SecurityToken", data)
	if err != nil {
		err = fmt.Errorf("refresh Ecs sts token err, fail to get SecurityToken: %s", err.Error())
		return
	}

	if accessKeyId == nil || accessKeySecret == nil || securityToken == nil {
		err = fmt.Errorf("there is no any available accesskey, secret and security token for Ecs role %s", ecsRoleName)
		return
	}

View on GitHub (pinned to d32a084675)