Multica Docs

トラブルシューティング

接続、実行、リアルタイム更新、メール、セルフホストサービスのよくある問題を診断します。

まず、問題がどの層で起きているかを切り分けます。Multica サービス、デーモン、ランタイム、AI コーディングツールのどれかです。多くの場合、次のコマンドだけで最初の有効なエラーが見つかります:

multica version
multica auth status
multica daemon status --output json
multica daemon logs --lines 100

セルフホストインスタンスでは、サービスを直接確認することもできます:

curl -i https://api.example.com/health
curl -i https://api.example.com/readyz

/health は API プロセスが応答していることだけを示します。/readyz はデータベースと migration も確認します。問題を報告するときは、エラー、関連ログ、CLI バージョン、OS を含め、トークンやメールアドレスなどの機微情報は提出前に取り除いてください。

デーモンが接続できない

まず次を実行します:

multica auth status
multica daemon status --output json
multica daemon logs --lines 100

よくある原因:

  • CLI がまだログインしていない、またはローカルに保存されたトークンが失効している。
  • デーモンが誤った Multica サービスに接続している。
  • 実行用コンピューターが API に到達できない、または DNS、TLS、ファイアウォールが接続を遮っている。
  • 現在のアカウントが対象ワークスペースのメンバーではなくなっている。
  • サポートされている AI コーディングツールがこのマシンに 1 つもインストールされておらず、デーモンが起動できない。

再ログインしてデーモンを再起動します:

multica login
multica daemon restart

セルフホストのデプロイでは、さらに実行用コンピューターから API の /health をリクエストしてください。サーバー本体でのテストでは、実行用コンピューター側の DNS、TLS、ファイアウォールの問題は見えません。アドレスを変更する場合は multica setup self-host を再実行するか、現在のプロファイルの server_url を確認します:

multica config show

タスクの実行が始まらない

タスクの実行ログを開き、まず作業の現在のステータスと待機理由を確認します。

queued ステータス

queued は、作業がまだランタイムに引き受けられるのを待っている状態です。順に確認します:

  1. エージェントに紐付いたランタイムはオンラインか。
  2. ランタイムは、そのエージェントに設定された AI コーディングツールを検出しているか。
  3. エージェントに利用可能な同時実行枠が残っているか。
  4. デーモンに全体の実行キャパシティが残っているか。

エージェントはデフォルトで最大 6 件、1 つのデーモンはデフォルトで最大 20 件の作業を同時に実行します。上限に達すると、新しい作業は実行中のものが終わるまでキューに残ります。ランタイムがオフラインの間も作業はキューに残り続け、そのランタイムが再接続猶予を超えてハートビートを停止し、かつ作業自身も同じ時間待った場合にのみ失敗します。取り込み中のランタイムの後ろに長い待ち行列ができても待ち時間を理由に失効することはなく、すでにオフラインのマシンに割り当てた場合も復帰させるための猶予がまるまる 1 回分残ります。

multica daemon status --output json
multica agent get <agent-id>
multica issue runs <issue-id>

ランタイム一覧に期待するツールが表示されない場合は、まず同じシステムアカウントと PATH でツールが実行でき、ログイン済みであることを確認してから、multica daemon restart を実行してください。

waiting_local_directory ステータス

これは、進行中の別の作業が同じローカルディレクトリを使っていることを意味します。2 つのエージェントが同じファイルを同時に変更しないよう、Multica はディレクトリロックの解放を待ちます。

この待機はディレクトリの in_place(「直接」)モードにのみ存在します。ディレクトリが git リポジトリであれば、リソースを worktree(「並行」)に切り替えるとキューそのものがなくなります。各作業が自分のワークツリーを受け取り、成果をブランチとして返すため、どの作業も待ちません。プロジェクトリソースを参照してください。

そうでなければ、通常は前の作業が終わるのを待つだけで十分です。前の作業が固まっている場合は、その実行ログから停止するか、現在のエージェントに別のローカルディレクトリを選んでください。このディレクトリの排他はデーモンがメモリ内で管理しており、ディスクにロックファイルは書き込まれません。ロック状態が異常だと疑われる場合は multica daemon restart で解放されます。手動で削除すべきファイルはありません。

AI コーディングツールが起動しない

デーモンがオンラインでも、ツール自体が使えるとは限りません。その実行の詳細記録を開き、次を重点的に確認します:

  • ツールのログインが完了しているか。
  • API key、クォータ、モデルの権限が利用可能か。
  • エージェントが選択したモデルと思考レベルを、そのツールがサポートしているか。
  • ローカルの作業ディレクトリが存在し、書き込み可能か。
  • エージェントのカスタム引数や環境変数が有効か。

まず実行用コンピューターのターミナルで、同じツールを直接実行してください。ツール単体でも起動できない場合は、先にツールのログインや設定を修復してから、実行ログから作業を再試行します。

リアルタイム更新が届かない

作業は実行されるのに、コメントやステータスがリアルタイムに反映されない場合は、たいてい WebSocket がつながっていません。

ブラウザ開発者ツールの Network → WS/ws 接続を確認します。セルフホストのデプロイでは、次を重点的に確認します:

  • FRONTEND_ORIGIN が、ブラウザで実際に開いているアドレスと一致しているか。
  • HTTPS のページが wss:// で接続しているか。
  • リバースプロキシが WebSocket の Upgrade リクエストを転送しているか。
  • ブラウザのログインが期限切れになっていないか。

curl/ws にアクセスして HTTP 400 が返るのは正常な動作です: このエンドポイントは workspace を指定するクエリパラメータを要求し、それらがないハンドシェイクは WebSocket アップグレードの前に拒否されます。したがって backend ログに 400/401 の記録があっても、通常の HTTP ルーティングが backend まで届いたことしか証明しません — プロキシが WebSocket Upgrade ヘッダーを保持していることの証明にはなりません。実際の接続を確認するには、ブラウザの DevTools → Network → WS タブ(または WebSocket 対応クライアント)で 101 ハンドシェイクが成立しているかを見てください。

セルフホストの注意: デーモンの長時間接続は /api/daemon/ws に向かいます(/ws ではありません)。同じように backend へ転送してください。ハンドシェイクが失敗するとデーモンは通知なくポーリングへフォールバックし、backend ログでこのパスに status=400 が繰り返し現れるのがその兆候です。

コンテナは作成時にしか .env を読み込みません。変更後は再作成してください:

docker compose -f docker-compose.selfhost.yml up -d

完全なリバースプロキシの例はセルフホストクイックスタートを参照してください。

multica setup がサーバーに到達できないと報告する

CLI の到達確認は <server-url>/health に GET を送り、200 を要求します。backend はこのパスを提供します。現在の web リリースは /health を backend へ転送しますが、古いリリースはそうではないため、すべてのトラフィックを古い frontend へ転送するリバースプロキシでは 404 が返り、CLI は稼働中のサーバーを到達不能と誤判定します。

プロキシで /health を backend(ポート 8080)へ明示的に転送すれば、すべてのリリースで動作します。セルフホストクイックスタートの 2 つの Caddy 例に含まれています。確認方法:

curl -fsS <server-url>/health

認証コードや招待メールが届かない

まず backend の起動ログを確認します。ログには、現在使っているのが Feishu webhookSMTP relayResend APIDEV mode のどれかが表示されます:

docker compose -f docker-compose.selfhost.yml logs backend \
  | grep "EmailService:"
  • Feishu webhook: MULTICA_VERIFICATION_FEISHU_WEBHOOK_URLMULTICA_VERIFICATION_FEISHU_SIGN_SECRET の両方が設定され、bot が対象グループに投稿できることを確認します。Feishu 設定がどちらか一つでも存在する場合、認証コードは Feishu だけを使い、メールにはフォールバックしません。
  • DEV mode: 配信は行われず、認証コードと招待リンクは backend ログに書き込まれるだけです。
  • Resend: API key が有効で、送信元アドレスのドメインが検証済みであることを確認します。
  • SMTP: ホスト、ポート、資格情報、送信元アドレスを確認し、エラーログから失敗が接続、TLS、認証、配送のどの段階で起きたかを判断します。

Feishu 設定が両方とも空の場合、認証コードは SMTP、次に Resend を使います。ワークスペース招待メールは引き続き Resend または SMTP を使います。設定方法はログインとサインアップを参照してください。

プロダクションではログ内の認証コードに依存せず、固定のローカルテスト認証コードも有効にしないでください。

添付ファイルのアップロードやダウンロードが失敗する

まず backend ログとレスポンスのステータスコードを確認します。よくある原因:

  • リバースプロキシがリクエストボディのサイズを制限している。
  • ローカルのアップロードディレクトリが書き込み不可、または永続ボリュームがマウントされていない。
  • S3 の bucket、region、endpoint、資格情報が一致していない。
  • ダウンロード URL がプロキシを経由した後、誤った公開ドメインやプロトコルを使っている。

Docker Compose では、デフォルトの backend_uploads volume がローカル添付ファイルを保存します。コンテナの再作成では削除されませんが、docker compose down -v はデータボリュームを削除します。S3 関連の設定は環境変数を参照してください。

使用量(Usage)が 0 のまま

Usage ページは 1 時間ごとのロールアップを読み取り、各作業の生の使用量を直接読みません。まず生データとロールアップテーブルを確認します:

SELECT count(*) FROM task_usage;
SELECT count(*) FROM task_usage_hourly;

SELECT plan_time, status, error_code, error_msg
FROM sys_cron_executions
WHERE job_name = 'rollup_task_usage_hourly'
ORDER BY plan_time DESC
LIMIT 20;

task_usage にデータがあり、ロールアップテーブルが空で、スケジューラーの記録が失敗を示している場合は、まず migration がすべて適用されていることを確認してください。migration 103 に拒否されてアップグレードできない場合は、次のセクションを参照してください。SQL の問題とスケジューリングの問題を切り分けるため、手動でロールアップを 1 回実行することもできます:

SELECT rollup_task_usage_hourly();

手動実行後に数値が正しければ、ロールアップ関数は動作しており、問題は backend の定期スケジューリング側にあります。手動 SQL は 1 回分のロールアップを補うだけで、スケジューリングを復旧させません。1 時間ごとのロールアップは backend 内蔵のスケジューラーが実行するため、pg_cron を自分で設定する必要はありません。

Migration 103 の失敗

通常のアップグレードでは、103 のために何かをする必要はありません。migrate up は適用前に過去の使用量データを自動でバックフィルします。空のデータベースはそのまま通過し、履歴のあるインスタンスは月ごとに補完されてから続行します。

それでも backend の起動が refusing to drop legacy daily rollups で失敗する場合は、自動バックフィルが完了していません(途中で失敗した、または migrate up を通さず SQL を直接適用した、など)。その場合はバックフィルコマンドを手動で実行し、完了後に backend を再起動します:

cd server
DATABASE_URL='postgres://...' go run ./cmd/backfill_task_usage_hourly

よく使うフラグ: --dry-run は書き込まずプレビューのみ、--sleep-between-slices はスライスの間に間隔を挟み、負荷の高いインスタンスへの読み取り圧力を下げます。コマンドは月単位のスライスで動作し、冪等なので、中断してもそのまま再実行できます。advisory lock を保持してサーバー側の定期ロールアップと相互排他になるため、重複や不整合なロールアップデータは生じません。完了後は backend を再起動し、/readyzmigrationsok になっていることを確認してください。

ポートが使用中

ローカルでよく使うポートは、API の 8080、Web の 3000、デーモンのヘルスチェックポートです。まず占有しているプロセスを特定します:

lsof -nP -iTCP:8080 -sTCP:LISTEN   # macOS / Linux
netstat -ano | findstr :8080       # Windows

それが別の Multica チェックアウトであれば、まずそのディレクトリで make stop を実行してください。そうでなければ、占有しているプログラムを通常の方法で停止するか、現在のサービスのポートを変更します。公開ポートの 80/443 は、Caddy や Nginx などのリバースプロキシがリッスンします。

ログの場所

コンポーネント確認方法
バックグラウンドのデーモンmultica daemon logs --lines 100
デーモンログのリアルタイム追跡multica daemon logs --follow
デフォルトプロファイルのログファイル~/.multica/daemon.log
デフォルトプロファイルの起動・クラッシュログ~/.multica/daemon.err.log
名前付きプロファイル~/.multica/profiles/<name>/ 配下の対応するログ
Docker backenddocker compose -f docker-compose.selfhost.yml logs -f backend
ブラウザ開発者ツールの Console と Network

どのファイルが現在有効なログかは、デーモンを起動したプロファイルによって決まります。以前のデーモンが残した古いログもそのまま読めてしまうため、誤ったファイルを調べてしまいがちです。当て推量でファイルを開かないでください: multica daemon logs は内容を流す前に、解決した絶対パスを表示します。名前付きプロファイルのログを読むときは --profile <name> を付けます。

デーモンの起動過程を直接観察したい場合は、フォアグラウンドで実行します:

multica daemon stop
multica daemon start --foreground

それでも特定できない場合は、GitHub Issues で既存の問題を検索するか、新しい issue を提出してください。

次のステップ

  • デーモンとランタイム — ランタイムの登録とオンライン状態の仕組み。
  • 作業 — ステータス、タイムアウト、失敗理由のリファレンス。
  • 環境変数 — セルフホスト設定の完全なリファレンス。