hashicorp/terraform · error

refresh Ecs sts token err, fail to get SecurityToken

Error message

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

What it means

Thrown while refreshing an ECS STS token: JMESPath search for 'SecurityToken' errored after AccessKeyId/AccessKeySecret resolved. The Success response object did not expose SecurityToken in a traversable shape.

Solutions

  1. Curl the metadata endpoint and confirm SecurityToken is present at the top level of the Success object.
  2. Force a credential refresh by re-attaching the RAM role.
  3. Update SDK and backend versions to match the metadata service contract.
  4. Verify there is no caching layer returning a partial document.
Defensive patterns

Strategy: validation

Validate before calling

tok, ok := data.(map[string]interface{})["SecurityToken"].(string)
if !ok || tok == "" {
    return fmt.Errorf("metadata missing SecurityToken")
}

Type guard

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

Prevention

When it happens

Trigger: Metadata endpoint returned Success with id/secret but the SecurityToken field is absent or nested in a non-traversable structure — e.g., the response shape changed to nest tokens under a sub-object, or a stale cached response omits the token.

Common situations: Credential rotation in progress where SecurityToken lags; region-specific metadata service differences; SDK/backend version mismatch.

Related errors


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

Appendix: source

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

		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
	}

	return accessKeyId.(string), accessKeySecret.(string), securityToken.(string), nil
}

func getHttpProxyUrl(rawUrl string) (*url.URL, error) {
	pc := httpproxy.FromEnvironment()
	u, err := url.Parse(rawUrl)
	if err != nil {
		return nil, err
	}
	return pc.ProxyFunc()(u)

View on GitHub (pinned to d32a084675)