hashicorp/terraform · error

refresh Ecs sts token err, fail to get Code

Error message

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

What it means

Thrown while refreshing an ECS (Elastic Compute Service) STS token from the ECS metadata service. After HTTP 200 and successful JSON parse, a JMESPath search for the 'Code' field failed. This means the parsed response body was not a JSON object graph that JMESPath could traverse (e.g., a bare array, scalar, or unexpected shape), so the search itself errored rather than returning nil.

Solutions

  1. From the instance, curl the ECS metadata URL directly (curl 'http://100.100.100.200/latest/meta-data/ram/security-credentials/<role-name>') and inspect the raw JSON shape.
  2. Confirm the response is a JSON object containing a 'Code' key; if the envelope differs, update the Alibaba Cloud ECS SDK or this backend to a version matching the metadata service contract.
  3. Verify no HTTP proxy is intercepting and rewriting the metadata response (check HTTP_PROXY/HTTPS_PROXY).
  4. Ensure the ECS instance actually has a RAM role attached; a missing role can produce a non-standard error body.
Defensive patterns

Strategy: validation

Validate before calling

// Before calling the metadata-backed refresh, sanity-check that the parsed body is an object.
// (Mirrors what the backend itself does; do this in your own wrapper / integration tests.)
var data interface{}
if err := json.Unmarshal(body, &data); err != nil { return err }
if _, ok := data.(map[string]interface{}); !ok {
    return fmt.Errorf("metadata response is not a JSON object: %T", data)
}

Type guard

// Ensure the parsed metadata body is a JSON object before JMESPath traversal.
func isJSONObject(v interface{}) bool {
    _, ok := v.(map[string]interface{})
    return ok
}

Prevention

When it happens

Trigger: Calling the ECS RAM role metadata endpoint (typically http://100.100.100.200/latest/meta-data/.../security-credentials/<role>) where the returned body parses as valid JSON but is not an object — for example a top-level array, a string, or a body whose shape changed because the metadata service returned an unexpected envelope.

Common situations: Running terraform init/plan on an ECS instance configured with an assumed RAM role, but the metadata service returned an error envelope in a non-object shape, or a proxy/middleware rewrote the response. Also seen when the ECS SDK version returns a different response structure than the JMESPath expression expects.

Related errors


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

Appendix: source

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

	err = responses.Unmarshal(response, httpResponse, "")
	if err != nil {
		err = fmt.Errorf("unmarshal Ecs sts token response err : %s", err.Error())
		return
	}

	if response.GetHttpStatus() != http.StatusOK {
		err = fmt.Errorf("get Ecs sts token err, httpStatus: %d, message = %s", response.GetHttpStatus(), response.GetHttpContentString())
		return
	}
	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 {

View on GitHub (pinned to d32a084675)