Skip to content

fix(main): tRPC 境界で例外をログに残す - #2474

Merged
hal-shu-sato merged 2 commits into
mainfrom
claude/trpc-log-errors
Aug 29, 2026
Merged

fix(main): tRPC 境界で例外をログに残す#2474
hal-shu-sato merged 2 commits into
mainfrom
claude/trpc-log-errors

Conversation

@hal-shu-sato

Copy link
Copy Markdown
Member

何が起きているか

procedure が投げた例外は、main のログに 1 行も残りません。

trpc-electroncreateIPCHandler{ createContext, router, windows } しか受け取らず、onError がありません。例外は renderer へ返り、renderer 側は catch して「エラーが発生しました。」を出します。結果として UI にエラーが出ているのにログが空という状態になります。

この経路に乗っているもの:

  • 入力検証の失敗(api/*.ts の手書きバリデータが投げる TypeError
  • 呼び出し元ウィンドウの解決失敗(winProcedureThe calling window was not found.
  • dataURL 未設定 / release 未検出(services/core.ts ほか)

なぜ今これを直すか

実運用に効いています。

open な bug issue 14 件を 1 件ずつ調べたところ、5 件が「たぶん直っているが、報告者に聞かないと確認できない」で止まりました#1430 #1561 #1883 #2123 #2180)。多くは Google フォーム経由の匿名報告で、症状が「エラーの発生」「画面が点滅する」のように薄いものです。ログが 1 枚あれば決着していました。

その他タブにはバグ報告のボタンはあるのにログを開くボタンがありませんが、導線を付けても中身が空では意味がないので、まずこちらを塞ぎます。

この PR でやること

境界に置けるのは middleware だけなので、そこに 1 つ足します。

const logErrors = t.middleware(async ({ next, path, type }) => {
  const result = await next();
  if (!result.ok) log.error(`trpc ${type} ${path} failed:`, result.error);
  return result;
});

export const procedure = t.procedure.use(logErrors);

procedure は 1 箇所からしか export しておらず、winProcedure / instProcedure / winInstProcedure はすべてこれ由来なので(src/t.procedure の直接使用はゼロ)、これだけで全 procedure に効きます。

next() は throw せず { ok: false, error } を返す(@trpc/server 11.18.0 の MiddlewareResult)ので、再 throw は不要です。

サービス層が既に log.error している経路とは重複しますが、そちらには「どの procedure の失敗か」が残りません。 pathtype はここでしか出せません。

検証

src/main/api/trpc.test.ts を足しました。失敗時にどの procedure かが分かる形でログに出ること、成功時には何も出ないこと。

middleware を外すと expected "spy" to be called 1 times, but got 0 times で落ちること、戻すと通ることを確認済みです。

  • yarn lint / yarn lint:ts / yarn test(310 件)緑
  • main プロセスの境界を触るので yarn packageyarn test:e2e(7 件)も回して緑

この PR に入れていないもの

renderer 側に } catch { で error オブジェクトを捨てている箇所が 13 ありますPackageActions.tsx 5、monacoEditorRenderer.tsx 3、ほか)。そちらは別 PR にします。

procedure が投げた例外は trpc-electron 経由で renderer へ返るだけで、
main のログには 1 行も残らない。renderer 側は catch して
「エラーが発生しました。」を出すので、**UI にエラーが出ているのに
ログが空**という状態になる。入力検証の失敗・窓の解決失敗・dataURL 未設定・
release 未検出はすべてこの経路で、いま何も記録されていない。

これは実運用に効いている。open な bug issue 14 件を調べたところ、5 件が
「たぶん直っているが報告者に聞かないと確認できない」で止まった。
その多くは Google フォーム経由の匿名報告で、ログが 1 枚あれば決着していた。

trpc-electron の createIPCHandler は onError を受け取らないため、境界に
置けるのは middleware だけ。procedure は 1 箇所からしか export しておらず
(winProcedure / instProcedure / winInstProcedure はすべてこれ由来)、
ここに足せば全 procedure に効く。

next() は throw せず ok:false を返すので再 throw は不要。サービス層が
既に log.error している経路とは重複するが、そちらにはどの procedure の
失敗かが残らないので、path と type はここでしか出せない。
失敗したときだけ、どの procedure かが分かる形でログに出ることを見る。
@hal-shu-sato
hal-shu-sato merged commit 78f35c1 into main Aug 29, 2026
9 checks passed
@hal-shu-sato
hal-shu-sato deleted the claude/trpc-log-errors branch August 29, 2026 18:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant