hashicorp/terraform · error

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

Error message

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

What it means

Returned by getAuthCredentialByEcsRoleName when jmespath.Search("Code", data) fails against the parsed metadata JSON. This indicates the JSON parsed (error 336 did not fire) but either lacks a 'Code' field or the JMESPath evaluation errored — typically the field is absent, meaning the response shape is unexpected.

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 c9def3e214)

Solutions

  1. curl the metadata URL and inspect the JSON structure — confirm a top-level "Code" field exists.
  2. Retry for transient metadata schema hiccups.
  3. If the role is misconfigured, re-attach the RAM role to the instance and confirm it returns the standard envelope.
  4. Fall back to static/STS credentials if the metadata shape stays non-standard.

Example fix

# before: metadata returns {"error":"role not found"} (no Code field)
ecs_role_name = "missing-role"

# after: attach a valid role whose metadata returns
# {"Code":"Success","AccessKeyId":...,...}
ecs_role_name = "attached-role"
Defensive patterns

Strategy: validation

Validate before calling

func metadataHasCode(role string) error {
    u := "http://100.100.100.200/latest/meta-data/ram/security-credentials/" + role
    resp, err := http.Get(u)
    if err != nil { return err }
    defer resp.Body.Close()
    var m map[string]interface{}
    json.NewDecoder(resp.Body).Decode(&m)
    if _, ok := m["Code"]; !ok {
        return fmt.Errorf("metadata response missing 'Code' field: %#v", m)
    }
    return nil
}

Try / catch

if _, err := getAuthCredentialByEcsRoleName(role); err != nil {
    if strings.Contains(err.Error(), "fail to get Code") {
        time.Sleep(2 * time.Second)
        return getAuthCredentialByEcsRoleName(role)
    }
    return err
}

Prevention

When it happens

Trigger: The metadata JSON lacks a top-level 'Code' key — e.g. it is a wrapped error object, an array, or an unexpected schema variant. jmespath.Search returns an error when evaluation fails (not merely when the key is missing, which returns nil).

Common situations: Metadata service returning a non-standard error envelope (still valid JSON) during a partial outage; SDK/schema drift in the metadata API; an intermediary returning a JSON error object instead of the credentials object.

Related errors


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