# SkillPatch skill: azure-data-tables-java

This skill guides agents in building table storage applications using the Azure Tables SDK for Java. It covers client creation with various authentication methods (connection string, shared key, SAS token, DefaultAzureCredential), core CRUD patterns for entities, and key concepts like partition keys, row keys, and table management. Compatible with both Azure Table Storage and Cosmos DB Table API.

You (the agent) were given this URL and asked to use this skill. This is a **public** skill — no SkillPatch account, API key, or prior setup is required. Two ways to use it:

**1. Use it right now** — the skill's complete file tree (SKILL.md + all reference files) is inlined below; read `SKILL.md` first, then follow it, consulting the other files as it directs.

**2. Install the exact package onto disk** (recommended if you can run a shell — this reproduces the skill byte-for-byte, including any binary assets that can't be inlined):

```bash
mkdir -p .claude/skills/azure-data-tables-java
curl -sSL https://skillpatch.dev/install_skill/azure-data-tables-java | tar -xz -C .claude/skills/
```

(`.claude/skills/` is Claude Code's convention; use whatever directory your agent loads skills from.)


---

## Skill files (2)

- `SKILL.md`
- `references/examples.md`


### `SKILL.md`

````markdown
---
name: azure-data-tables-java
description: Build table storage applications with Azure Tables SDK for Java. Use when working with Azure Table Storage or Cosmos DB Table API for NoSQL key-value data, schemaless storage, or structured data at scale.
license: MIT
metadata:
  author: Microsoft
  version: "1.0.0"
  package: com.azure:azure-data-tables
---

# Azure Tables SDK for Java

Build table storage applications using the Azure Tables SDK for Java. Works with both Azure Table Storage and Cosmos DB Table API.

## Installation

```xml
<dependency>
  <groupId>com.azure</groupId>
  <artifactId>azure-data-tables</artifactId>
  <version>12.6.0-beta.1</version>
</dependency>
```

## Client Creation

### With Connection String

```java
import com.azure.data.tables.TableServiceClient;
import com.azure.data.tables.TableServiceClientBuilder;
import com.azure.data.tables.TableClient;

TableServiceClient serviceClient = new TableServiceClientBuilder()
    .connectionString("<your-connection-string>")
    .buildClient();
```

### With Shared Key

```java
import com.azure.core.credential.AzureNamedKeyCredential;

AzureNamedKeyCredential credential = new AzureNamedKeyCredential(
    "<account-name>",
    "<account-key>");

TableServiceClient serviceClient = new TableServiceClientBuilder()
    .endpoint("<your-table-account-url>")
    .credential(credential)
    .buildClient();
```

### With SAS Token

```java
TableServiceClient serviceClient = new TableServiceClientBuilder()
    .endpoint("<your-table-account-url>")
    .sasToken("<sas-token>")
    .buildClient();
```

### With DefaultAzureCredential (Storage only)

```java
import com.azure.core.credential.TokenCredential;
import com.azure.identity.AzureIdentityEnvVars;
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.ManagedIdentityCredentialBuilder;

// Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
TokenCredential credential = new DefaultAzureCredentialBuilder()
    .requireEnvVars(AzureIdentityEnvVars.AZURE_TOKEN_CREDENTIALS)
    .build();
// Or use a specific credential directly in production:
// See https://learn.microsoft.com/java/api/overview/azure/identity-readme?view=azure-java-stable#credential-classes
// TokenCredential credential = new ManagedIdentityCredentialBuilder().build();

TableServiceClient serviceClient = new TableServiceClientBuilder()
    .endpoint("<your-table-account-url>")
    .credential(credential)
    .buildClient();
```

## Key Concepts

- **TableServiceClient**: Manage tables (create, list, delete)
- **TableClient**: Manage entities within a table (CRUD)
- **Partition Key**: Groups entities for efficient queries
- **Row Key**: Unique identifier within a partition
- **Entity**: A row with up to 252 properties (1MB Storage, 2MB Cosmos)

## Core Patterns

### Create Table

```java
// Create table (throws if exists)
TableClient tableClient = serviceClient.createTable("mytable");

// Create if not exists (no exception)
TableClient tableClient = serviceClient.createTableIfNotExists("mytable");
```

### Get Table Client

```java
// From service client
TableClient tableClient = serviceClient.getTableClient("mytable");

// Direct construction
TableClient tableClient = new TableClientBuilder()
    .connectionString("<connection-string>")
    .tableName("mytable")
    .buildClient();
```

### Create Entity

```java
import com.azure.data.tables.models.TableEntity;

TableEntity entity = new TableEntity("partitionKey", "rowKey")
    .addProperty("Name", "Product A")
    .addProperty("Price", 29.99)
    .addProperty("Quantity", 100)
    .addProperty("IsAvailable", true);

tableClient.createEntity(entity);
```

### Get Entity

```java
TableEntity entity = tableClient.getEntity("partitionKey", "rowKey");

String name = (String) entity.getProperty("Name");
Double price = (Double) entity.getProperty("Price");
System.out.printf("Product: %s, Price: %.2f%n", name, price);
```

### Update Entity

```java
import com.azure.data.tables.models.TableEntityUpdateMode;

// Merge (update only specified properties)
TableEntity updateEntity = new TableEntity("partitionKey", "rowKey")
    .addProperty("Price", 24.99);
tableClient.updateEntity(updateEntity, TableEntityUpdateMode.MERGE);

// Replace (replace entire entity)
TableEntity replaceEntity = new TableEntity("partitionKey", "rowKey")
    .addProperty("Name", "Product A Updated")
    .addProperty("Price", 24.99)
    .addProperty("Quantity", 150);
tableClient.updateEntity(replaceEntity, TableEntityUpdateMode.REPLACE);
```

### Upsert Entity

```java
// Insert or update (merge mode)
tableClient.upsertEntity(entity, TableEntityUpdateMode.MERGE);

// Insert or replace
tableClient.upsertEntity(entity, TableEntityUpdateMode.REPLACE);
```

### Delete Entity

```java
tableClient.deleteEntity("partitionKey", "rowKey");
```

### List Entities

```java
import com.azure.data.tables.models.ListEntitiesOptions;

// List all entities
for (TableEntity entity : tableClient.listEntities()) {
    System.out.printf("%s - %s%n",
        entity.getPartitionKey(),
        entity.getRowKey());
}

// With filtering and selection
ListEntitiesOptions options = new ListEntitiesOptions()
    .setFilter("PartitionKey eq 'sales'")
    .setSelect("Name", "Price");

for (TableEntity entity : tableClient.listEntities(options, null, null)) {
    System.out.printf("%s: %.2f%n",
        entity.getProperty("Name"),
        entity.getProperty("Price"));
}
```

### Query with OData Filter

```java
// Filter by partition key
ListEntitiesOptions options = new ListEntitiesOptions()
    .setFilter("PartitionKey eq 'electronics'");

// Filter with multiple conditions
options.setFilter("PartitionKey eq 'electronics' and Price gt 100");

// Filter with comparison operators
options.setFilter("Quantity ge 10 and Quantity le 100");

// Top N results
options.setTop(10);

for (TableEntity entity : tableClient.listEntities(options, null, null)) {
    System.out.println(entity.getRowKey());
}
```

### Batch Operations (Transactions)

```java
import com.azure.data.tables.models.TableTransactionAction;
import com.azure.data.tables.models.TableTransactionActionType;
import java.util.Arrays;

// All entities must have same partition key
List<TableTransactionAction> actions = Arrays.asList(
    new TableTransactionAction(
        TableTransactionActionType.CREATE,
        new TableEntity("batch", "row1").addProperty("Name", "Item 1")),
    new TableTransactionAction(
        TableTransactionActionType.CREATE,
        new TableEntity("batch", "row2").addProperty("Name", "Item 2")),
    new TableTransactionAction(
        TableTransactionActionType.UPSERT_MERGE,
        new TableEntity("batch", "row3").addProperty("Name", "Item 3"))
);

tableClient.submitTransaction(actions);
```

### List Tables

```java
import com.azure.data.tables.models.TableItem;
import com.azure.data.tables.models.ListTablesOptions;

// List all tables
for (TableItem table : serviceClient.listTables()) {
    System.out.println(table.getName());
}

// Filter tables
ListTablesOptions options = new ListTablesOptions()
    .setFilter("TableName eq 'mytable'");

for (TableItem table : serviceClient.listTables(options, null, null)) {
    System.out.println(table.getName());
}
```

### Delete Table

```java
serviceClient.deleteTable("mytable");
```

## Typed Entities

```java
public class Product implements TableEntity {
    private String partitionKey;
    private String rowKey;
    private OffsetDateTime timestamp;
    private String eTag;
    private String name;
    private double price;
    
    // Getters and setters for all fields
    @Override
    public String getPartitionKey() { return partitionKey; }
    @Override
    public void setPartitionKey(String partitionKey) { this.partitionKey = partitionKey; }
    @Override
    public String getRowKey() { return rowKey; }
    @Override
    public void setRowKey(String rowKey) { this.rowKey = rowKey; }
    // ... other getters/setters
    
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public double getPrice() { return price; }
    public void setPrice(double price) { this.price = price; }
}

// Usage
Product product = new Product();
product.setPartitionKey("electronics");
product.setRowKey("laptop-001");
product.setName("Laptop");
product.setPrice(999.99);

tableClient.createEntity(product);
```

## Error Handling

```java
import com.azure.data.tables.models.TableServiceException;

try {
    tableClient.createEntity(entity);
} catch (TableServiceException e) {
    System.out.println("Status: " + e.getResponse().getStatusCode());
    System.out.println("Error: " + e.getMessage());
    // 409 = Conflict (entity exists)
    // 404 = Not Found
}
```

## Environment Variables

```bash
# Storage Account
AZURE_TABLES_CONNECTION_STRING=DefaultEndpointsProtocol=https;AccountName=...  # Alternative to Entra ID auth
AZURE_TABLES_ENDPOINT=https://<account>.table.core.windows.net  # Required for all auth methods
AZURE_TOKEN_CREDENTIALS=prod  # Required only if DefaultAzureCredential is used in production

# Cosmos DB Table API
COSMOS_TABLE_ENDPOINT=https://<account>.table.cosmosdb.azure.com  # Alternative endpoint for Cosmos DB Table API
```

## Best Practices

1. **Partition Key Design**: Choose keys that distribute load evenly
2. **Batch Operations**: Use transactions for atomic multi-entity updates
3. **Query Optimization**: Always filter by PartitionKey when possible
4. **Select Projection**: Only select needed properties for performance
5. **Entity Size**: Keep entities under 1MB (Storage) or 2MB (Cosmos)

## Trigger Phrases

- "Azure Tables Java"
- "table storage SDK"
- "Cosmos DB Table API"
- "NoSQL key-value storage"
- "partition key row key"
- "table entity CRUD"

````


### `references/examples.md`

````markdown
# Azure Data Tables SDK for Java - Examples

Comprehensive code examples for the Azure Data Tables SDK for Java.

## Table of Contents
- [Maven Dependency](#maven-dependency)
- [Client Creation](#client-creation)
- [Creating Tables](#creating-tables)
- [CRUD Operations on Entities](#crud-operations-on-entities)
- [Querying Entities](#querying-entities)
- [Batch/Transactional Operations](#batchtransactional-operations)
- [Async Client Patterns](#async-client-patterns)
- [Error Handling](#error-handling)

## Maven Dependency

```xml
<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-data-tables</artifactId>
    <version>12.6.0-beta.1</version>
</dependency>

<!-- For DefaultAzureCredential authentication -->
<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-identity</artifactId>
    <version>1.18.2</version>
</dependency>
```

## Client Creation

### TableServiceClient with DefaultAzureCredential

```java
import com.azure.core.credential.TokenCredential;
import com.azure.data.tables.TableServiceClient;
import com.azure.data.tables.TableServiceClientBuilder;
import com.azure.identity.DefaultAzureCredentialBuilder;

TokenCredential tokenCredential = new DefaultAzureCredentialBuilder().build();
TableServiceClient tableServiceClient = new TableServiceClientBuilder()
    .endpoint("<your-table-account-url>")
    .credential(tokenCredential)
    .buildClient();
```

### TableServiceClient with Connection String

```java
TableServiceClient tableServiceClient = new TableServiceClientBuilder()
    .connectionString("<your-connection-string>")
    .buildClient();
```

### TableServiceClient with Named Key Credential

```java
import com.azure.core.credential.AzureNamedKeyCredential;

AzureNamedKeyCredential credential = new AzureNamedKeyCredential(
    "<your-account-name>", 
    "<account-access-key>"
);
TableServiceClient tableServiceClient = new TableServiceClientBuilder()
    .endpoint("<your-table-account-url>")
    .credential(credential)
    .buildClient();
```

### TableServiceClient with SAS Token

```java
TableServiceClient tableServiceClient = new TableServiceClientBuilder()
    .endpoint("<your-table-account-url>")
    .sasToken("<sas-token-string>")
    .buildClient();
```

### TableClient (Direct Table Access)

```java
import com.azure.data.tables.TableClient;
import com.azure.data.tables.TableClientBuilder;

// Using endpoint and credential
TableClient tableClient = new TableClientBuilder()
    .endpoint("https://myaccount.table.core.windows.net/")
    .credential(new AzureNamedKeyCredential("name", "key"))
    .tableName("myTable")
    .buildClient();

// Using connection string
TableClient tableClient = new TableClientBuilder()
    .connectionString("<your-connection-string>")
    .tableName("myTable")
    .buildClient();
```

### Get TableClient from TableServiceClient

```java
TableClient tableClient = tableServiceClient.getTableClient("myTable");
System.out.printf("Table name: %s%n", tableClient.getTableName());
```

## Creating Tables

### Create Table

```java
import com.azure.data.tables.TableClient;

String tableName = "myTable";
TableClient tableClient = tableServiceClient.createTable(tableName);
System.out.printf("Created table: %s%n", tableClient.getTableName());
```

### Create Table If Not Exists (Idempotent)

```java
TableClient tableClient = tableServiceClient.createTableIfNotExists(tableName);
```

### Create with Response

```java
import com.azure.core.http.rest.Response;
import com.azure.core.util.Context;
import java.time.Duration;

Response<TableClient> response = tableServiceClient.createTableWithResponse(
    "myTable", 
    Duration.ofSeconds(5), 
    new Context("key1", "value1")
);
System.out.printf("Status: %d, Table: %s%n", 
    response.getStatusCode(), 
    response.getValue().getTableName());
```

### Delete Table

```java
tableServiceClient.deleteTable("myTable");
```

## CRUD Operations on Entities

### Create Entity

```java
import com.azure.data.tables.models.TableEntity;

String partitionKey = "OfficeSupplies";
String rowKey = "s001";

TableEntity entity = new TableEntity(partitionKey, rowKey)
    .addProperty("Product", "Marker Set")
    .addProperty("Price", 5.00)
    .addProperty("Quantity", 21)
    .addProperty("Type", "Pen");

tableClient.createEntity(entity);
System.out.printf("Created entity: %s/%s%n", partitionKey, rowKey);
```

### Create Entity with Response

```java
Response<Void> response = tableClient.createEntityWithResponse(
    entity, 
    Duration.ofSeconds(5), 
    new Context("key1", "value1")
);
System.out.printf("Status: %d%n", response.getStatusCode());
```

### Get Entity

```java
TableEntity retrievedEntity = tableClient.getEntity(partitionKey, rowKey);
System.out.printf("Retrieved: %s/%s%n", 
    retrievedEntity.getPartitionKey(), 
    retrievedEntity.getRowKey());

// Access properties
Object product = retrievedEntity.getProperty("Product");
Object price = retrievedEntity.getProperty("Price");
```

### Get Entity with Select

```java
import java.util.Arrays;
import java.util.List;

List<String> propertiesToSelect = Arrays.asList("Product", "Price");

Response<TableEntity> response = tableClient.getEntityWithResponse(
    partitionKey, 
    rowKey, 
    propertiesToSelect, 
    Duration.ofSeconds(5), 
    new Context("key1", "value1")
);

TableEntity entity = response.getValue();
entity.getProperties().forEach((key, value) ->
    System.out.printf("%s: %s%n", key, value));
```

### Update Entity (Merge)

```java
import com.azure.data.tables.models.TableEntityUpdateMode;

TableEntity entityForUpdate = new TableEntity(partitionKey, rowKey)
    .addProperty("Type", "Pen")
    .addProperty("Color", "Red");

// MERGE mode: merges with existing entity (default)
tableClient.updateEntity(entityForUpdate);

// Explicit MERGE
tableClient.updateEntity(entityForUpdate, TableEntityUpdateMode.MERGE);
```

### Update Entity (Replace)

```java
// REPLACE mode: replaces entire entity
tableClient.updateEntity(entityForUpdate, TableEntityUpdateMode.REPLACE);
```

### Update with ETag (Optimistic Concurrency)

```java
Response<Void> response = tableClient.updateEntityWithResponse(
    entityForUpdate, 
    TableEntityUpdateMode.REPLACE, 
    true,  // ifUnchanged - use ETag
    Duration.ofSeconds(5), 
    new Context("key1", "value1")
);
```

### Upsert Entity (Insert or Update)

```java
TableEntity entityForUpsert = new TableEntity(partitionKey, "s002")
    .addProperty("Type", "Marker")
    .addProperty("Color", "Blue");

// Insert if not exists, update if exists
tableClient.upsertEntity(entityForUpsert);
```

### Delete Entity

```java
// By keys
tableClient.deleteEntity(partitionKey, rowKey);

// By entity object
tableClient.deleteEntity(entity);

// With response
Response<Void> response = tableClient.deleteEntityWithResponse(
    entity, 
    true,  // ifUnchanged - use ETag
    Duration.ofSeconds(5), 
    new Context("key1", "value1")
);
```

## Querying Entities

### List All Entities

```java
import com.azure.core.http.rest.PagedIterable;

PagedIterable<TableEntity> entities = tableClient.listEntities();

entities.forEach(entity ->
    System.out.printf("Entity: %s/%s%n", 
        entity.getPartitionKey(), 
        entity.getRowKey()));
```

### List with Filter and Select

```java
import com.azure.data.tables.models.ListEntitiesOptions;
import java.util.Arrays;

List<String> propertiesToSelect = Arrays.asList("Product", "Price");

ListEntitiesOptions options = new ListEntitiesOptions()
    .setFilter(String.format("PartitionKey eq '%s'", partitionKey))
    .setSelect(propertiesToSelect);

for (TableEntity entity : tableClient.listEntities(options, null, null)) {
    System.out.printf("%s: %.2f%n", 
        entity.getProperty("Product"), 
        entity.getProperty("Price"));
}
```

### Advanced Query with Top

```java
ListEntitiesOptions options = new ListEntitiesOptions()
    .setTop(15)  // Limit results
    .setFilter("PartitionKey eq 'MyPartitionKey' and RowKey eq 'MyRowKey'")
    .setSelect(Arrays.asList("name", "lastname", "age"));

PagedIterable<TableEntity> entities = tableClient.listEntities(
    options,
    Duration.ofSeconds(5), 
    null
);

entities.forEach(entity -> {
    System.out.printf("Entity: %s/%s%n", 
        entity.getPartitionKey(), 
        entity.getRowKey());
    entity.getProperties().forEach((key, value) ->
        System.out.printf("  %s: %s%n", key, value));
});
```

### Filter Operators

```java
// Equals
"PartitionKey eq 'Sales'"

// Not equals
"PartitionKey ne 'Sales'"

// Greater than
"Price gt 10.0"

// Greater than or equal
"Quantity ge 100"

// Less than
"Price lt 50.0"

// Less than or equal
"Quantity le 10"

// And
"PartitionKey eq 'Sales' and Price gt 10.0"

// Or
"Type eq 'Pen' or Type eq 'Marker'"
```

### List Tables

```java
import com.azure.data.tables.models.ListTablesOptions;
import com.azure.data.tables.models.TableItem;

// List all tables
for (TableItem tableItem : tableServiceClient.listTables()) {
    System.out.println(tableItem.getName());
}

// List with filter
ListTablesOptions options = new ListTablesOptions()
    .setFilter(String.format("TableName eq '%s'", tableName));

for (TableItem tableItem : tableServiceClient.listTables(options, null, null)) {
    System.out.println(tableItem.getName());
}
```

## Batch/Transactional Operations

All entities in a transaction must have the same partition key.

```java
import com.azure.data.tables.models.TableTransactionAction;
import com.azure.data.tables.models.TableTransactionActionType;
import com.azure.data.tables.models.TableTransactionResult;

import java.util.ArrayList;
import java.util.List;

List<TableTransactionAction> transactionActions = new ArrayList<>();

String partitionKey = "markers";  // All entities MUST have same partition key

// CREATE action
TableEntity firstEntity = new TableEntity(partitionKey, "m001")
    .addProperty("Type", "Dry")
    .addProperty("Color", "Red");
transactionActions.add(new TableTransactionAction(
    TableTransactionActionType.CREATE, 
    firstEntity
));

// CREATE action
TableEntity secondEntity = new TableEntity(partitionKey, "m002")
    .addProperty("Type", "Wet")
    .addProperty("Color", "Blue");
transactionActions.add(new TableTransactionAction(
    TableTransactionActionType.CREATE, 
    secondEntity
));

// UPDATE_MERGE action
TableEntity entityToUpdate = new TableEntity(partitionKey, "m003")
    .addProperty("Brand", "Crayola")
    .addProperty("Color", "Blue");
transactionActions.add(new TableTransactionAction(
    TableTransactionActionType.UPDATE_MERGE, 
    entityToUpdate
));

// DELETE action
TableEntity entityToDelete = new TableEntity(partitionKey, "m004");
transactionActions.add(new TableTransactionAction(
    TableTransactionActionType.DELETE, 
    entityToDelete
));

// Submit transaction
TableTransactionResult result = tableClient.submitTransaction(transactionActions);

// Check results
System.out.println("Transaction status codes:");
result.getTransactionActionResponses().forEach(response ->
    System.out.printf("  %d%n", response.getStatusCode()));
```

### Transaction Action Types

```java
TableTransactionActionType.CREATE          // Insert new entity
TableTransactionActionType.UPDATE_MERGE    // Merge with existing entity
TableTransactionActionType.UPDATE_REPLACE  // Replace entire entity
TableTransactionActionType.UPSERT_MERGE    // Insert or merge
TableTransactionActionType.UPSERT_REPLACE  // Insert or replace
TableTransactionActionType.DELETE          // Delete entity
```

## Async Client Patterns

### Create Async Clients

```java
import com.azure.data.tables.TableServiceAsyncClient;
import com.azure.data.tables.TableAsyncClient;

TableServiceAsyncClient asyncServiceClient = new TableServiceClientBuilder()
    .connectionString("<connection-string>")
    .buildAsyncClient();

TableAsyncClient asyncTableClient = new TableClientBuilder()
    .connectionString("<connection-string>")
    .tableName("myTable")
    .buildAsyncClient();
```

### Create Entity Async

```java
TableEntity entity = new TableEntity("partitionKey", "rowKey")
    .addProperty("Name", "Async Entity");

asyncTableClient.createEntity(entity)
    .subscribe(
        unused -> System.out.println("Entity created"),
        error -> System.err.println("Error: " + error.getMessage()),
        () -> System.out.println("Completed")
    );
```

### Query Entities Async

```java
asyncTableClient.listEntities()
    .subscribe(
        entity -> System.out.printf("Entity: %s/%s%n", 
            entity.getPartitionKey(), 
            entity.getRowKey()),
        error -> System.err.println("Error: " + error.getMessage())
    );
```

### Transaction Async

```java
asyncTableClient.submitTransaction(transactionActions)
    .subscribe(
        result -> {
            System.out.println("Transaction completed");
            result.getTransactionActionResponses().forEach(r ->
                System.out.printf("Status: %d%n", r.getStatusCode()));
        },
        error -> System.err.println("Transaction failed: " + error.getMessage())
    );
```

## Error Handling

### Sync Error Handling

```java
import com.azure.core.exception.HttpResponseException;
import com.azure.data.tables.models.TableServiceException;

try {
    tableClient.createEntity(entity);
} catch (TableServiceException e) {
    System.err.println("Table service error: " + e.getMessage());
    System.err.println("Status code: " + e.getResponse().getStatusCode());
    System.err.println("Error code: " + e.getValue().getErrorCode());
} catch (HttpResponseException e) {
    System.err.println("HTTP error: " + e.getResponse().getStatusCode());
} catch (Exception e) {
    System.err.println("Unexpected error: " + e.getMessage());
}
```

### Transaction Error Handling

```java
import com.azure.data.tables.models.TableTransactionFailedException;

try {
    tableClient.submitTransaction(transactionActions);
} catch (TableTransactionFailedException e) {
    System.err.println("Transaction failed");
    System.err.println("Failed action index: " + e.getFailedTransactionActionIndex());
    System.err.println("Status code: " + e.getResponse().getStatusCode());
}
```

### Async Error Handling

```java
asyncTableClient.createEntity(entity)
    .subscribe(
        unused -> System.out.println("Success"),
        error -> {
            if (error instanceof TableServiceException) {
                TableServiceException tse = (TableServiceException) error;
                System.err.println("Error code: " + tse.getValue().getErrorCode());
            } else {
                System.err.println("Error: " + error.getMessage());
            }
        }
    );
```

````
