ファイルを選択
  1. base64hub
  2. Base64 を学ぶ
  3. Base64 のエラー
トラブルシューティング

Base64 のデコードエラーと直し方

Base64 の失敗の大半は、アルファベットの誤り、パディングの不足、余計な文字、文字コードの誤り、二重エンコードの 5 つが原因です。下の一覧から表示されたエラーメッセージを探し、対処法へ進んでください。

エラーメッセージの一覧

メッセージ表示される場所最も考えられる原因
binascii.Error: Incorrect paddingPython の base64.b64decode末尾の = の不足。Base64URL や途中で切れた文字列によることが多い
binascii.Error: Invalid base64-encoded string: number of data characters (5) cannot be 1 more than a multiple of 4Python入力が途中で切れている、または -/_ が黙って捨てられた
binascii.Error: Only base64 data is allowedvalidate=True を付けた Python入力に改行、スペース、-、_ が含まれている
InvalidCharacterError: Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.Chrome、EdgeBase64URL の文字、ゴミ文字、長さの誤り
InvalidCharacterError: String contains an invalid characterFirefox同上
InvalidCharacterError: Invalid characterNode.js の atob同上
IllegalArgumentException(“Illegal base64 character …")Java の java.util.Base64アルファベットに合わないデコーダー、または改行
FormatException.NET の Convert.FromBase64StringBase64URL の文字、またはパディングの不足
base64: invalid inputGNU coreutils の base64 -dアルファベット外の文字

デコーダーのエラーを直す

Python の「Incorrect padding」

Base64 の出力の長さは常に 4 の倍数で、末尾が = でパディングされています。Python のデコーダーはこのパディングを要求します。

>>> import base64
>>> base64.b64decode("SGVsbG8")
Traceback (most recent call last):
  ...
binascii.Error: Incorrect padding
>>> base64.b64decode("SGVsbG8=")
b'Hello'

パディングがないのは、たいてい文字列が Base64URL である(JWT、URL トークン、多くの API は = を省きます)か、何かが末尾を削ったためです。パディングを戻してください。

s = "SGVsbG8"
s += "=" * (-len(s) % 4)

長さが 4 の倍数より 1 多い場合は、パディングでは解決できません。このとき Python は number of data characters (5) cannot be 1 more than a multiple of 4 を報告します。余った 1 文字は 6 ビットしか持たないので、データの一部が欠けています。文字列が途中で切れていなくても、このメッセージが出ることがあります。validate=True がないと、Python は - と _ を含むアルファベット外の文字を捨ててしまいます。base64.b64decode("SGk_Pg==") は _ を捨て、データ文字が 5 つになります。Base64URL の入力には base64.urlsafe_b64decode を使ってください。

「Invalid character」と atob の失敗

ブラウザは同じアルファベットで atob を実装していますが、エラーの文言は異なります。Chrome は “The string to be decoded is not correctly encoded”、Firefox は “String contains an invalid character”、Node.js は “Invalid character” と表示します。いずれも、次の入力に対して InvalidCharacterError をスローします。

  • Base64URL の文字。 atob("SGk_Pg") は _ のせいで失敗します。先に - を + に、_ を / に置き換えてください。
  • 空白を除いた長さが 4n+1。 たとえば atob("A") です。
  • 場違いな文字。 JSON からコピーした引用符、data: 接頭辞、URL エンコードによる %2F などです。

atob が見逃してくれることもあります。スペースや改行を読み飛ばし、長さのつじつまが合えばパディングの不足も受け付けるので、atob("SGVsbG8") は "Hello" を返します。逆向きのエラー、つまり btoa が “characters outside of the Latin1 range” で失敗するのは Unicode テキストの問題で、Uint8Array.toBase64 で取り上げています。

両方のアルファベット、空白、パディングの不足に対応する寛容なデコーダー:

function decodeLoose(s) {
  s = s.replace(/\s+/g, "").replace(/-/g, "+").replace(/_/g, "/");
  s += "=".repeat((4 - (s.length % 4)) % 4);
  return Uint8Array.from(atob(s), (c) => c.charCodeAt(0));
}

new TextDecoder().decode(decodeLoose("SGk_Pg")); // "Hi?>"

Python で同等のもの:

import base64

def b64decode_any(s: str) -> bytes:
    s = "".join(s.split())
    s = s.replace("-", "+").replace("_", "/")
    s += "=" * (-len(s) % 4)
    return base64.b64decode(s, validate=True)

Base64 の修復 ツールは同じクリーンアップを行い、何を変更したかを教えてくれます。

Java の「Illegal base64 character」と .NET の FormatException

Java の java.util.Base64 には 3 つのデコーダーがあり、それぞれ自分のアルファベットに厳格です。メッセージは問題の文字を 16進数で示します。5f は _、2d は -、2f は /、20 はスペース、a は改行です。

入力に含まれるもの使うデコーダー
+ と /Base64.getDecoder()
- と _Base64.getUrlDecoder()
改行(MIME、PEM の本文)Base64.getMimeDecoder()

基本のデコーダーは改行とスペースを拒否しますが、パディングの不足は受け付けるので、SGVsbG8 は問題なくデコードされます。

.NET の Convert.FromBase64String は、Base64URL の文字やパディングの不足に対して FormatException をスローします。スペースと改行は読み飛ばします。呼び出す前に、上で示したようにアルファベットとパディングを直してください。完全な例は Java での Base64 と C# での Base64 にあります。

テキストが文字化けする

デコードは成功したのに、テキストがおかしく見える場合です。Base64 が保存するのはバイト列で、そのバイト列は何らかの文字コードでテキストから作られています。別の文字コードで読み戻すと文字化けします。

見えるもの元のテキスト起きたこと
CaféCaféUTF-8 のバイト列を Latin-1 や Windows-1252 として読んだ
Caf�CaféWindows-1252 のバイト列を UTF-8 として読んだ
H e l l o または H\0e\0l\0l\0o\0HelloUTF-16LE のバイト列を UTF-8 として読んだ

1 行目は atob の典型的な罠です。atob は 1 バイトを 1 文字に対応させるため、atob("Q2Fmw6k=") は "Café" を返します。代わりにバイト列を UTF-8 としてデコードしてください。

const bytes = Uint8Array.from(atob("Q2Fmw6k="), (c) => c.charCodeAt(0));
new TextDecoder().decode(bytes); // "Café"

UTF-16LE は Windows のツールでよく見かけます。PowerShell の -EncodedCommand や多くの .NET API がこれを生成します。Base64 からテキストへの変換 では正しく読めるまで文字コードを切り替えられ、Base64 から UTF-16 はワイド文字のケースを扱います。

出力がバイナリのように見える

デコード結果が � や制御文字だらけだったり、PNG、PK、%PDF といった断片が含まれていたりするなら、ペイロードはファイルです。Base64 の先頭の文字を見てください。iVBORw0KGgo なら PNG、JVBERi0 なら PDF、H4sI なら gzip です。一覧は よくある Base64 の接頭辞 にあります。データは、形式を判定してダウンロードできる Base64 からファイルへの変換 で開いてください。H4sI には gzip Base64 のデコード を使います。

デコード結果が期待と異なるバイト列になる

エラーは出ないのに、バイト列が違う場合です。よくある理由は次のとおりです。

  • エンコード時の末尾の改行。 echo "hello" | base64 は(\n 付きの)aGVsbG8K になり、echo -n "hello" | base64 は aGVsbG8= になります。printf '%s' か echo -n を使ってください。
  • + がスペースになった。 URL のクエリ文字列やフォームの本文では、+ はスペースを意味します。URLSearchParams("t=PGI+Ym9sZDwvYj4=").get("t") は PGI Ym9sZDwvYj4= を返します。この後、例外をスローするデコーダーもあれば、スペースを捨てておかしなデータを生成するデコーダーもあります。Base64 を URL に入れる前に encodeURIComponent でパーセントエンコードするか、Base64URL を使ってください。
  • パーセントエンコードが残っている。 SGk%2FPg%3D%3D は、Base64 としてデコードする前に URL デコードして SGk/Pg== に戻す必要があります。
  • JSON からコピーしたエスケープ。 生の JSON から文字列をコピーすると、リテラルの \n(2 文字)が紛れ込むことがあります。Python の寛容なデコーダーはバックスラッシュを捨てて n を残し、エラーなしで誤ったバイト列を返します。b64decode("SGVs\\nbG8=") は b'Hel\x9d\xb1\xbc' になります。コピーするのではなく、JSON をパースしてください。JSON Base64 デコーダー はすべてのフィールドに対してこれを行います。
  • 空白の扱いが厳格か寛容か。 validate=True なしの Python、atob、.NET、Java の MIME デコーダーは改行を読み飛ばします。validate=True 付きの Python と Java の基本のデコーダーは改行を拒否します。MIME と PEM のデータは 76 文字か 64 文字で折り返されているので、それを受け付けるデコーダーを選んでください。

二重にエンコードされたデータ

U0dWc2JHOGdkMjl5YkdRaA== をデコードすると SGVsbG8gd29ybGQh になり、これも有効な Base64 で、デコードすると Hello world! になります。1 回デコードした結果が Base64 の文字だけで構成され、長さが 4 の倍数なら、二重エンコードを疑ってください。

Kubernetes Secret でよく起こります。data: の下の値は Base64 で、kubectl create secret --from-literal はエンコードを代わりに行ってくれます。先に自分で値をエンコードしてしまうと、Pod にはパスワードではなく Base64 のテキストが渡ります。平文の値には stringData: を使うか、Kubernetes Secret デコーダー で保存内容を確認してください。迷ったときは、Base64 バリデーター で文字列が有効かどうかと、何バイトのデータを含むかを確認できます。

よくある質問

binascii.Error: Incorrect padding を解消するには?

長さが 4 の倍数になるまで = を付け足します:s += "=" * (-len(s) % 4)。文字列が Base64URL なら、さらに - を + に、_ を / に置き換えるか、base64.urlsafe_b64decode を使ってください。

JWT を atob でデコードすると失敗するのはなぜですか?

JWT は - と _ を含む Base64URL を使いますが、atob が知っているのは + と / だけだからです。先に文字を変換するか、トークンを JWT デコーダー に貼り付けてください。

デコードしたテキストが é ではなく é と文字化けするのはなぜですか?

バイト列は UTF-8 なのに、Latin-1 や Windows-1252 として読まれたためです。JavaScript なら TextDecoder、Python なら .decode("utf-8") などで、バイト列を UTF-8 としてデコードしてください。

長さが 4n+1 の Base64 文字列は修復できますか?

できません。余った 1 文字は 6 ビットしか持たず 1 バイトに満たないので、少なくとも 1 文字が欠けています。元のデータを探すか、文字列がどこで切れたかを確認してください。

データが二重に Base64 エンコードされているかどうかを見分けるには?

一度デコードしてみてください。結果が再び A-Z a-z 0-9 + / = だけからなる、長さが 4 の倍数の文字列なら、もう一度デコードします。

続けて読む