aws-samples / aws-samples/generative-ai-use-cases

convertToSafeFilename が全角スペースを素通りさせ、日本語ファイル名の添付が失敗する

Open
#1,671 4 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
1.4k
Forks
433
Avg merge
2h 35m
Merged PRs (30d)
1

Description

### 概要

チャットユースケースで書類を添付すると、ファイル名に全角スペース(U+3000)が含まれている場合に Bedrock Converse API が `ValidationException` を返し、添付が失敗します。ファイルサイズ・形式とは無関係です。

確認バージョン: v5.5.0 / main(2026-08-21 時点で未修正)

### 原因

`packages/cdk/lambda/utils/fileNameUtils.ts` の `convertToSafeFilename`:

```ts
const safeName = nameWithoutExt.replace(/[^a-zA-Z0-9\s\-()[\]]/g, '_');
```

JavaScript の `\s` は U+3000(全角スペース)やタブにマッチするため、これらは「許可文字」として置換されず残ります。しかし Bedrock の `DocumentBlock.name` はこれらを受け付けません。

漢字・かなは `_` に置換されて問題なく通るため、**空白系の文字だけがサニタイズを素通りしている**状態です。日本語のファイル名では全角スペースが区切りとして日常的に使われるため、実務上かなりの頻度で発生します。

### 発生するエラー

```
ValidationException: The document file name can only contain alphanumeric characters,
whitespace characters, hyphens, parentheses, and square brackets. The name can't contain
more than one consecutive whitespace character. Check that the file name conforms to
these restrictions and retry your request.
```

エラー文は「連続する空白は不可」とだけ述べていますが、実測では**全角スペースは1つでも拒否されます**。

### 実測結果

Bedrock Converse API / `jp.anthropic.claude-haiku-4-5-20251001-v1:0` で `document.name` のみを変えて検証しました。

| document.name | 結果 |
|---|---|
| `testname` / `test-name` / `test(1)` / `test[1]` | OK |
| `test name`(半角スペース1つ) | OK |
| `" testname"` / `"testname "`(前後の半角スペース) | OK |
| `test_name` / `test__name` | **OK**(アンダースコアはエラー文に列挙されていないが実際は許容される) |
| `test name`(全角スペース1つ) | **NG** |
| `test name`(半角スペース2連) | **NG** |
| `test\tname`(タブ) | **NG** |
| `""`(空文字) | NG(`valid min length: 1`) |
| 300 文字 | NG(長さ上限あり) |

### 再現手順

1. `テスト 資料.xlsx` のように、名前の途中に全角スペースを含むファイルを用意する
2. チャットユースケースで添付して送信する
3. 回答が返らず、Lambda のログに上記 `ValidationException` が出力される

### 影響

自社環境で 1 日分の添付を集計したところ、**添付された書類のうち約 19%** がこの理由で失敗していました。形式にはほとんど依存しません(xls / doc / xlsx / docx / pdf いずれも 11〜18%)。

### 修正案

```ts
const safeName = nameWithoutExt
.replace(/[^a-zA-Z0-9 \-()[\]]/g, '_') // \s ではなく ASCII 半角スペースのみ許可
.replace(/ {2,}/g, ' ') // 連続する空白を 1 つに畳む
.trim();
```

加えて、置換後が空文字になった場合のフォールバックと、名前長の上限も必要かと思います。

### 同じパターンが AgentCore 経路にもあります

`packages/web/src/utils/strandsUtils.ts` の `convertFileToStrandsContentBlock`:

```ts
const fileName = file.name.replace(/[^a-zA-Z0-9\s\-()[\]]/g, 'X');
```

置換文字は `X` ですが、`\s` を許可している点は同一です。

### 関連

本件でエラーになっても、利用者にはファイル名が原因であることが伝わりません → #1672

Contributor guide

Open the contributing guide

Research direction

Read convertToSafeFilename in packages/cdk/lambda/utils/fileNameUtils.ts first, then compare the filename handling in packages/web/src/utils/strandsUtils.ts. Verify the examples in the issue, especially full-width spaces, tabs, repeated ASCII spaces, empty results, and long names. Done means both paths produce names accepted by their downstream APIs without breaking the allowed punctuation.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, typescript
Domain
api, backend, full-stack
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.