メインコンテンツへスキップ

終了コード

arc の各コマンドは、結果を終了コードとして報告します —— 成功は 0、それに加えて 7 種類の異なる非ゼロ値があります(うち 1 つは予約されていますがまだ発生しません)—— そのためスクリプトはメッセージを読まずに、どの種類の失敗に当たったかを判別できます。

arc のどのコマンドも、スクリプトで分岐判断できる数字を返して終了します。非ゼロ値が複数あることこそが要点です:「指定したパスが存在しない」「コマンドをタイプミスした」「daemon が動いていない」——この 3 つはスクリプトに 3 種類の異なる対応を求めるものであり、それらを見分けるために英語のエラーテキストをパターンマッチする必要はどこにもないはずです。

終了コード意味範囲
0コマンドが要求どおりに実行されたすべてのコマンド
1存在しない —— あるいは service start の場合は、すでに存在するすべてのコマンド
2権限拒否予約済み —— このリリースではどのコマンドもこれを返さない(下記参照)
3インスタンスは記録上存在するが、動いていない(stoppedstartingarc service status
4インスタンスは動作中として記録されているが、そのプロセスは既に存在しない(deadarc service status
5ランタイムエラー。すべての使い方の誤りを含むすべてのコマンド
6コマンドが daemon を必要としたが、動いている daemon がなかったすべてのコマンド
7llm レンダラーを持たないコマンドで --view llm が要求された各コマンドの --view llm

「範囲」の列に注意してください。上記の 34arc service status がインスタンスレコードをどう読むかという、そのコマンド自身の解釈であって、CLI 全体についての約束ではありません:他の場所ではこの 2 つの数字はランタイムの汎用的な意味を持ちます —— 3 は衝突、4 は部分的成功 —— そして 4 には実際に発生させるものがあります。一部のプロバイダーが成功し、他が失敗するバッチ arc did issue です。rc == 4 を「daemon が死んだ」と読むスクリプトは、そのバッチを誤読します。4 で分岐するのは arc service status に対してだけにしてください。

2 は列挙型には存在しますが、このリリースにはこれを発生させるものがありません。下記の 2 の節では、これが推測ではなくどのように確認されたかを示します。7 は狭い範囲に限定されています:これは llm レンダラーを持たないコマンドで --view llm を使ったときにのみ発生し、どのコマンドも --view default / --view json / --view human は変わらず受け付けます。

以下の各節は、それが説明する状況を実際に実行したものであり、arc 2.0.0-beta.48(commit 5a5316bde、2026-09-10)に対して取得されています。バージョン番号だけでは、どのビルドを使っているかは分かりません —— 2.0.0-beta.48 は今回のサイクルで複数のバイナリを指してきました —— そのため、このページの出力をバイト単位で信用する前に arc --version を実行し、その第 3 フィールドである commit を、ここに載っているものと比較してください。この表は「これらのコードが何を意味するか」として読んでください。arc が返しうる数字の完全な集合としては読まないでください:ここに挙がっていない何らかの形で失敗するコマンドも非ゼロで終了しますし、後のリリースで新しいコードが現れることもあります。

0 —— コマンドが要求どおりに実行された

bash
$ arc service list
NAME          ID                PORT   STATUS   HOME                          SOURCES
(no instances)

結果が空でも成功です。列挙して何も見つからないことは失敗ではありません —— 存在しない特定のものを要求すること、それが 1 につながります。

1 —— 存在しない、または既に存在する

存在しないパスを読む:

bash
$ arc afs read /no-such-file --instance notes
ERROR: No data found for path: /no-such-file

作られたことのないインスタンスを名指しする:

bash
$ arc service status --instance nope
ERROR: no instance named "nope". `arc service list` shows 1

そして —— 覚えておく価値があるケース —— すでに起動しているインスタンスを start しようとする:

bash
$ arc service start --instance notes
ERROR: instance "notes" is already running
       pid 93652, port 61430, started 15s ago
       use `arc service restart --instance notes` or pick another name

最後のケースは 5 ではなく 1 です。このコードは「名指ししたものが、必要としていた状態になかった」ということを意味し、存在しないケースと既に存在するケースの両方をカバーします。これは使い方の誤りではないので、5 ではありません。

2 —— 権限拒否。定義されているがまだ発生しない

ランタイムの終了コード列挙は 2PermissionDeniedError のために予約しており、そのクラス自体は CLI 自身のエラーモジュールに存在します。ただ、このリリースではそれを投げるものが何もありません:どのコマンドも PermissionDeniedError を構築しませんし、CLI の下にある AFS 層から発生する権限エラーもそれには変換されず —— 通常のエラーとしてそのまま伝播していき、他の未処理の失敗と同じく 5 に落ち着きます。これは推測ではなく確認済みです:chmod 000 で作った読めないファイルが、実際の挙動をそのまま再現します。

bash
$ arc afs read /vault/locked.txt --standalone
ERROR: EACCES: permission denied, open '/tmp/arc-perm-test/secret/locked.txt'

このコマンドは 5 で終了します。2 は、プロトコルが CLI が今のところ区別していない何かのために取っておいた数字だと捉えてください。実際に目にするものではありません。

3 —— インスタンスは存在するが、動いていない

bash
$ arc service stop --instance notes
Service stopped: notes
$ arc service status --instance notes
  Instance: notes
  ID:       ab5aa97074c454a0
  Status:   stopped
  PID:      93652
  Port:     61430
  URL:      http://127.0.0.1:61430
  Home:     /tmp/arc-docs-demo/notes
  Note:     PID / Port / URL above are the LAST KNOWN values from this instance's previous run, not a live process.

上記では VersionCommitCheckoutSpaceSourcesHostStarted のいくつかのフィールドが省略されています。pid、port、URL は stop した後も引き続き報告され、Note: の行が、それらが過去の値であることを言葉で説明しています —— --json では同じ事実が lastKnown マーカーとして表れます。

starting も同様に 3 を返します。これは「起動待ちループ」を書く際に重要です:3 は「まだ準備できていない」を意味し、「来ない」ではありません。コールドスタートではこの窓は数秒間で、status のポーリングは stoppedstarting(exit 3)→ up(exit 0)という経路をたどります。3 は「待ち続ける」、4 は「もう待たない」と捉えてください。

4 —— 動作中として記録されているが、プロセスは既にない

通常のコマンドの並びではここには到達しません。このコードが表すのは選択ではなく損傷だからです。これを見るには、インスタンスを start してからその daemon を直接 kill し、レジストリの行が up を主張し続ける一方で背後のプロセスは既に存在しない、という状態を作ります:

start は自分自身の完全なステータスブロックを表示します。次のステップで必要な pid は、その PID: の行にあります。以下の 2 つのブロックは、ここで重要なフィールドだけに絞っています。

bash
$ arc service start --instance notes --home /tmp/arc-docs-demo/notes
  Instance: notes
  Status:   up
  PID:      95288
  Port:     61430
  Home:     /tmp/arc-docs-demo/notes
$ kill -9 95288
$ arc service status --instance notes
  Instance: notes
  ID:       ab5aa97074c454a0
  Status:   dead
  PID:      95288
  Port:     61430
  URL:      http://127.0.0.1:61430
  Home:     /tmp/arc-docs-demo/notes
  Note:     PID / Port / URL above are the LAST KNOWN values from this instance's previous run, not a live process.

dead は、クラッシュ、OOM kill、再起動など、arc service stop を経由せずにプロセスが終わったときに得られます。3 との区別には意味があります:stopped は誰かが選んだ状態であり、dead は誰も選んでいない状態です。arc service gc が削除するのはこの状態の、そしてこの状態だけのレコードです。

5 —— ランタイムエラー。使い方の誤りも含む

これは最も広いコードです。コマンドラインを間違えるあらゆる方法がここに落ちます。次の 3 つの例では、以下に示す内容の後にそれぞれ関連する使い方のテキストも表示されます —— 最初の例では完全なコマンド一覧、残り 2 つではそのコマンド自身のヘルプです。未知のコマンド:

bash
$ arc serivce list
ERROR: Unknown command: "serivce"

Did you mean?
  arc serve
  arc service

未知のオプション:

bash
$ arc service list --bogus
ERROR: Unknown argument: bogus

必須の引数が足りない場合:

bash
$ arc space rm
ERROR: Not enough non-option arguments: got 0, need at least 2

そして、コマンドラインを通過した後、ランタイムがルーティングできないリクエスト:

bash
$ arc afs exec /no-such-action --instance notes
ERROR: No module found for path: /no-such-action in namespace 'default'

5 は「コマンド自体は正しく動き、実世界の問題を報告した」場合もカバーします —— arc network doctor は、いずれかのチェックが失敗すると 5 で終了します。つまり 5 だけでは、自分が何か書き間違えたのか、外の何かが壊れているのかは分かりません。それを伝えるのがメッセージの役目です。

6 —— コマンドが daemon を必要としたが、動いている daemon がなかった

bash
$ arc afs ls /
ERROR: No AFS daemon is running for instance "default".
Start it with:  arc service start
Or use --standalone for ad-hoc mode (no runtime state)

2 行目に表示される提案コマンドは、実際にあなたが打ったフラグだけをそのまま返します —— --instance--home を省略すれば裸の arc service start を提案し、自分で --instance foo --home ~/foo を渡せば、まさにそれをそのまま提案し、打っていない値を出すことは決してありません。6 が存在するのは、メッセージを読まなくてもこのケースを 5 と区別できるようにするためです。daemon を起動すれば解決できる前提条件の未達は、コマンドが失敗したこととは別物であり、エラーテキストがその解決策を名指ししています。同じ 6 は、default に限らず、daemon が stopped または dead である名前付きインスタンスでも返ってきます。

7 —— --view llm が要求されたが、このコマンドはそれを描画できない

--view llm はグローバルに受け付けられますが、すべてのコマンドがそのための llm レンダラーを持っているわけではなく、実装されていない場合はデフォルトビューへ黙ってフォールバックするのではなく fail closed します。arc network doctor には llm レンダラーがありません:

bash
$ arc network doctor --view llm
ERROR: --view llm is not implemented for `network doctor`. This command has no llm renderer (declare ⇒ execute; will not silently fall back to default).

arc afs ls はそれを実装しており、それをサポートするコマンドで同じフラグを使うと成功します:

bash
$ arc afs ls / --standalone --view llm
ENTRY /spaces CHILDREN=-1 DESC="Local DID Space logical roots"
ENTRY /peers CHILDREN=-1 DESC="Dispatchable ARC hosts (always includes local)"
ENTRY /ash CHILDREN=-1 DESC="ASH pipeline DSL for deterministic data pipelines"
ENTRY /dev CHILDREN=-1
ENTRY /modules CHILDREN=-1
ENTRY /team CHILDREN=-1
ENTRY /.knowledge KIND=afs:system CHILDREN=-1 DESC="Provider capability index"
ENTRY /.meta KIND=afs:system CHILDREN=-1 DESC="Root metadata and mount info"
ENTRY /.actions KIND=afs:system CHILDREN=-1 DESC="Root-level executable actions"
TOTAL 9

スクリプトにとって重要な区別はこうです:認識されない --view の値(例えば --view bogus)は、引数解析の時点で捕まる使い方の誤りであり、他の不正なフラグと同じく 5 で終了します ——

bash
$ arc service list --view bogus
ERROR: Invalid values:
  Argument: view, Given: "bogus", Choices: "default", "llm", "human", "json"

—— 一方、llm レンダラーを持たないコマンドで使う --view llm は、正当で認識される値ではあるものの、そのコマンドが対応できないだけであり、7 で終了します。この区別がなければ、スクリプトは英語テキストを解析せずに「フラグの打ち方を間違えた」のか「フラグは合っているが、このコマンドがまだサポートしていない」のかを見分けられません。