floci-io/floci · error · AwsException

BadRequestException

BadRequestException

Error message

Invalid resource ARN: " + arn

What it means

Thrown by API Gateway v1 tagging operations (TagResource/UntagResource/ListTagsForResource) when the supplied Resource-arn does not contain the literal segment '/restapis/'. Floci's ApiGatewayTagHandler.apiIdFromArn() splits the ARN on '/restapis/' and requires at least two parts; anything else (an ARN for a different resource type, a raw API id, or a malformed string) cannot yield an apiId and is rejected as BadRequestException (HTTP 400).

Source

Thrown at src/main/java/io/github/hectorvent/floci/services/apigateway/ApiGatewayTagHandler.java:56

    @Override
    public Map<String, String> listTags(String region, String arn) {
        return service.getTags(region, apiIdFromArn(arn));
    }

    @Override
    public void tagResource(String region, String arn, Map<String, String> tags) {
        service.tagResource(region, apiIdFromArn(arn), tags);
    }

    @Override
    public void untagResource(String region, String arn, List<String> tagKeys) {
        service.untagResource(region, apiIdFromArn(arn), tagKeys);
    }

    private static String apiIdFromArn(String arn) {
        String[] parts = arn.split("/restapis/");
        if (parts.length < 2) {
            throw new AwsException("BadRequestException", "Invalid resource ARN: " + arn, 400);
        }
        return parts[1].split("/")[0];
    }
}

View on GitHub (pinned to 62ff490619)

Solutions

  1. Use the canonical v1 RestApi ARN format: arn:aws:apigateway:<region>::/restapis/<apiId> (empty account field is correct for apigateway).
  2. For HTTP APIs (v2) use the apigatewayv2 TagResource operation and its ARN format arn:aws:apigateway:<region>::/apis/<apiId> instead of the v1 endpoint.
  3. Retrieve the correct ARN from the API's ARN attribute (GetRestApi / Fn::GetAtt RestApi.Arn) rather than hand-building it.
  4. Add a preflight assertion in your tagging code that the ARN contains '/restapis/' before invoking the API.

Example fix

# before
aws --endpoint-url http://localhost:4566 apigateway tag-resource \
  --resource-arn arn:aws:apigateway:us-east-1::/apis/abc1234567 --tags k=v

# after (v1 REST API)
aws --endpoint-url http://localhost:4566 apigateway tag-resource \
  --resource-arn arn:aws:apigateway:us-east-1::/restapis/abc1234567 --tags k=v
Defensive patterns

Strategy: validation

Validate before calling

// Java: build and check the v1 ARN before tagging
String arn = "arn:aws:apigateway:" + region + "::/restapis/" + apiId;
if (arn.split("/restapis/").length < 2 || arn.split("/restapis/")[1].isBlank()) {
    throw new IllegalArgumentException("Not a v1 RestApi ARN: " + arn);
}
service.tagResource(region, arn, tags);

Try / catch

catch (AwsException e) {
    if ("BadRequestException".equals(e.getCode()) && e.getMessage().contains("Invalid resource ARN")) {
        // ARN shape is wrong: log and surface a config error, do not retry
        throw new ConfigurationException("Tagging requires arn:aws:apigateway:<region>::/restapis/<apiId>", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling aws apigateway tag-resource --resource-arn <arn> with an ARN whose resource part is not 'restapis/<apiId>' — e.g. arn:aws:apigateway:us-east-1::/usageplans/abc123, a RestApi id like 'abc123' with no ARN wrapper, or a v2 (HTTP API) ARN of the form ...:/apis/<id> routed at the v1 tagging endpoint.

Common situations: Mixing API Gateway v1 (REST) and v2 (HTTP) ARN formats — v2 uses /apis/, not /restapis/. Copying an execute-api ARN, a stage ARN, or passing the API id directly because the console shows it. Tagging usage plans, domain names, or other API Gateway sub-resources whose ARNs this handler does not model.

Understand the failure class

Background: BadRequestException (HTTP 400) — NestJS 'Bad Request' Errors: Why They Fire and How to Fix Them — this error's family across 4 libraries.

Related errors


AI-assisted analysis of floci-io/floci@62ff490619 (2026-08-14). Data as JSON: /api/errors/846a4563dfbde9c6. Report an issue: GitHub.