# GetBucketTagging

GetBucketTagging returns the tag set of a bucket. Buckets on STRG carry no tags, so there is
never a tag set to return: the operation checks that the bucket exists and answers
`404 NoSuchTagSet` - the same answer Amazon S3 gives for a bucket without tags. Tools that read
bucket tags while describing or managing a bucket, such as Terraform's `aws_s3_bucket` resource,
read that answer as "no tags" and carry on unchanged.

**Info: Good to know on STRG**

- Buckets have no tags, so GetBucketTagging always answers `404 NoSuchTagSet` for a bucket that
  exists.
- PutBucketTagging is answered with `501 NotImplemented`, so a client knows straight away, and
  [DeleteBucketTagging](https://docs.strg.com/s3-api/DeleteBucketTagging) succeeds and leaves the bucket as it was.
- Every access key can call it, on every bucket the key reaches.
- `x-amz-expected-bucket-owner` is welcome and has nothing to check: a key only ever reaches
  buckets of its own account.

## When you'd use it

- **Infrastructure as code.** Terraform's `aws_s3_bucket` resource, and similar tools that
  compare a bucket with its configuration, read the bucket's tags along the way. The
  `NoSuchTagSet` answer tells them there are none, so a plan shows no tag changes.
- **Describing a bucket.** The AWS CLI and inventory scripts that gather everything about a
  bucket ask for its tags too, and record an empty set.
- **Scripts written for Amazon S3.** Code that already treats `NoSuchTagSet` as "no tags" - as
  most code does, since that is S3's own answer for an untagged bucket - runs unchanged against
  STRG.

## Request

```http
GET /?tagging HTTP/1.1
Host: my-bucket.s3.eu-central-1.strg.com
Authorization: AWS4-HMAC-SHA256 Credential=...
x-amz-date: 20260926T120000Z
x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
```

The path-style form is `GET /my-bucket?tagging` on `s3.eu-central-1.strg.com` -
[Addressing](https://docs.strg.com/s3-api/overview#addressing) explains both.

### Permissions

Every access key can call this operation: **Read bucket settings** (`buckets:read-config`) is
always included. A key limited to certain buckets reaches only those buckets, and any other
bucket answers `403 AccessDenied`. [Access keys](https://docs.strg.com/access-keys#always-included) has the
details.

### URI parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `Bucket` | String | Yes | The bucket whose tag set is read. |
| `tagging` | Flag | Yes | Selects this operation. Sent with no value. |

Any other query parameter is answered `501 NotImplemented`, so a client knows straight away that
it has no effect here.

### Request headers

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `x-amz-expected-bucket-owner` | String | No | Welcome, with nothing to check: an access key only ever reaches its own account's buckets. |

### Request body

None.

## Response

STRG answers this operation with `404 NoSuchTagSet` for every bucket that exists, never with
`200 OK`.

### Response headers

| Name | Description |
| --- | --- |
| `Content-Type` | `application/xml`. |
| `x-amz-request-id` | The request ID, handy for a support request. |

### Response body

An S3 error document. For a virtual-hosted request to `my-bucket`:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <Code>NoSuchTagSet</Code>
  <Message>The TagSet does not exist</Message>
  <Resource>/</Resource>
  <BucketName>my-bucket</BucketName>
  <RequestId>4442587FB7D0A2F9</RequestId>
</Error>
```

For reference, these are the members of the success response Amazon S3 defines. STRG never
returns them, since a bucket has no tags to put in them.

| Element | Type | Description |
| --- | --- | --- |
| `Tagging` | Container | The root element. |
| `TagSet` | Container | The bucket's tags. |
| `Tag` | Container | One tag, with a `Key` and a `Value`. |

## Errors

These are the answers this request can return, and the situation behind each one.

| Code | HTTP status | When |
| --- | --- | --- |
| `NoSuchTagSet` | 404 | Always, once the bucket is confirmed to exist. It means "no tags", exactly as on Amazon S3. |
| `NoSuchBucket` | 404 | The bucket does not exist, it is in a region other than the endpoint's, or the account has no storage in this endpoint's region yet. |
| `AccessDenied` | 403 | The access key is limited to buckets that do not include this one, the account is not active, or the request is unsigned. |
| `InvalidAccessKeyId` | 403 | The access key does not exist, has expired or been revoked - or it was created moments ago and is not usable in this endpoint's region yet, where the account already stores data, in which case the same request works shortly afterwards. |
| `SignatureDoesNotMatch` | 403 | The request signature does not match. |
| `RequestTimeTooSkewed` | 403 | The request time is more than 15 minutes from the server's. |
| `AuthorizationHeaderMalformed` | 400 | The signature's credential scope names a region other than the endpoint's. |
| `NotImplemented` | 501 | The request carries a query parameter this operation does not take. |
| `SlowDown` | 503 | Too many requests. The `Retry-After` header says when a retry is welcome; the AWS SDKs retry on their own. |
| `ServiceUnavailable` | 503 | A temporary failure; the same request can be retried. |
| `InternalError` | 500 | An unexpected failure while checking the bucket; the same request can be retried. |

## Differences from Amazon S3

The table lists each place where STRG behaves differently, and what that means for a client.

| Aspect | Amazon S3 | STRG |
| --- | --- | --- |
| Bucket tags | Stored, and returned by this operation | Buckets have no tags; this operation always answers `404 NoSuchTagSet`, S3's own answer for "no tags" |
| Permission | `s3:GetBucketTagging`, granted per identity | Included in every access key, for every bucket the key reaches |
| Bucket in another region | `301` redirect with `x-amz-bucket-region` | `404 NoSuchBucket`. A bucket is reached through its own regional endpoint. |
| `x-amz-expected-bucket-owner` | Checked against the bucket owner | Welcome, with nothing to check |

## Examples

Reading the tag set of `my-bucket` in `eu-central-1`, with `NoSuchTagSet` taken as an empty set:

**AWS CLI**

```bash
aws s3api get-bucket-tagging \
  --bucket my-bucket \
  --endpoint-url https://s3.eu-central-1.strg.com \
  --region eu-central-1
```

The command prints `An error occurred (NoSuchTagSet)` and exits with a non-zero code - the CLI's
way of saying the bucket has no tags.

**Python (boto3)**

```python
import boto3
from botocore.exceptions import ClientError

s3 = boto3.client(
    "s3",
    endpoint_url="https://s3.eu-central-1.strg.com",
    region_name="eu-central-1",
)

try:
    tags = s3.get_bucket_tagging(Bucket="my-bucket")["TagSet"]
except ClientError as error:
    if error.response["Error"]["Code"] != "NoSuchTagSet":
        raise
    tags = []

print(tags)
```

**JavaScript (AWS SDK v3)**

```javascript
import { GetBucketTaggingCommand, S3Client } from "@aws-sdk/client-s3";

const client = new S3Client({
  endpoint: "https://s3.eu-central-1.strg.com",
  region: "eu-central-1",
});

let tags;
try {
  ({ TagSet: tags } = await client.send(new GetBucketTaggingCommand({ Bucket: "my-bucket" })));
} catch (error) {
  if (error.name !== "NoSuchTagSet") throw error;
  tags = [];
}

console.log(tags);
```

## Related

- [DeleteBucketTagging](https://docs.strg.com/s3-api/DeleteBucketTagging)
- [GetObjectTagging](https://docs.strg.com/s3-api/GetObjectTagging)
- [DeleteObjectTagging](https://docs.strg.com/s3-api/DeleteObjectTagging)
- [Access keys](https://docs.strg.com/access-keys)
- [S3 API overview](https://docs.strg.com/s3-api/overview) - including the [other S3 operations](https://docs.strg.com/s3-api/overview#other-s3-operations)
