[{"data":1,"prerenderedAt":408},["ShallowReactive",2],{"content-/chrome-extension-mf-bug-fix":3,"all-pages-for-dir":406,"og-image-/chrome-extension-mf-bug-fix":407},{"id":4,"title":5,"body":6,"category":387,"description":388,"extension":389,"meta":390,"navigation":98,"path":391,"project_name":392,"published":393,"publishedAt":394,"seo":395,"stem":396,"tags":397,"todo":403,"updatedAt":404,"__hash__":405},"pages/2026-04/2026-04-01/chrome-extension-mf-bug-fix.md","Chrome拡張 会計ソフト連携 - statusCallback未渡しバグ修正・インポート検証強化・繰越処理API調査",{"type":7,"value":8,"toc":363},"minimark",[9,13,17,20,25,30,33,36,47,128,139,142,145,147,150,154,157,161,164,171,175,185,202,205,207,211,214,217,220,228,239,242,245,256,259,262,268,287,290,292,296,300,303,306,325,331,335,342,345,347,350,353,356,359],[10,11,5],"h1",{"id":12},"chrome拡張-会計ソフト連携-statuscallback未渡しバグ修正インポート検証強化繰越処理api調査",[14,15,16],"p",{},"会計ソフトAのChrome拡張で仕訳インポートを実行したら、進捗表示が一切動かなかった。ステータスバーが「処理中...」のまま固まり、でもネットワークタブを覗くとリクエスト自体は飛んでいる。原因を追うと、コールバック関数の渡し忘れが4箇所見つかった。そこから芋づる式にインポートのレスポンス検証不足、繰越処理APIの調査へと一日が流れた。",[18,19],"hr",{},[21,22,24],"h2",{"id":23},"statuscallback未渡しバグの発見と修正","statusCallback未渡しバグの発見と修正",[26,27,29],"h3",{"id":28},"症状-進捗表示が動かない","症状: 進捗表示が動かない",[14,31,32],{},"仕訳インポートの一括処理を走らせたとき、ポップアップUIの進捗バーが0%のまま止まっていた。コンソールにエラーは出ない。リクエストは正常に飛んで200が返ってくる。処理自体は走っているのに、UIだけが更新されない。",[26,34,35],{"id":35},"原因の特定",[14,37,38,42,43,46],{},[39,40,41],"code",{},"switchAndConfirmCti","関数のシグネチャを確認すると、第3引数に",[39,44,45],{},"statusCallback","を受け取る設計になっている。呼び出し元を洗い出すと、4箇所中4箇所すべてで第3引数が省略されていた。",[48,49,54],"pre",{"className":50,"code":51,"language":52,"meta":53,"style":53},"language-javascript shiki shiki-themes vitesse-light vitesse-light","// Before: statusCallbackを渡し忘れ\nawait switchAndConfirmCti(page, targetCti);\n\n// After: 第3引数にコールバックを渡す\nawait switchAndConfirmCti(page, targetCti, statusCallback);\n","javascript","",[39,55,56,65,93,100,106],{"__ignoreMap":53},[57,58,61],"span",{"class":59,"line":60},"line",1,[57,62,64],{"class":63},"sxvE3","// Before: statusCallbackを渡し忘れ\n",[57,66,68,72,76,80,84,87,90],{"class":59,"line":67},2,[57,69,71],{"class":70},"sHkkW","await",[57,73,75],{"class":74},"senZ8"," switchAndConfirmCti",[57,77,79],{"class":78},"shFtX","(",[57,81,83],{"class":82},"s4oTP","page",[57,85,86],{"class":78},",",[57,88,89],{"class":82}," targetCti",[57,91,92],{"class":78},");\n",[57,94,96],{"class":59,"line":95},3,[57,97,99],{"emptyLinePlaceholder":98},true,"\n",[57,101,103],{"class":59,"line":102},4,[57,104,105],{"class":63},"// After: 第3引数にコールバックを渡す\n",[57,107,109,111,113,115,117,119,121,123,126],{"class":59,"line":108},5,[57,110,71],{"class":70},[57,112,75],{"class":74},[57,114,79],{"class":78},[57,116,83],{"class":82},[57,118,86],{"class":78},[57,120,89],{"class":82},[57,122,86],{"class":78},[57,124,125],{"class":82}," statusCallback",[57,127,92],{"class":78},[14,129,130,131,134,135,138],{},"コールバックが",[39,132,133],{},"undefined","で入ってきても関数内部で",[39,136,137],{},"statusCallback?.()","のようにオプショナルチェーンで呼んでいたため、エラーにならず黙って握りつぶされていた。エラーが出ないバグは発見が遅れる。4箇所すべてに第3引数を追加して修正完了。",[26,140,141],{"id":141},"教訓",[14,143,144],{},"オプショナルチェーンは安全だが、必須のコールバックまでオプショナルにすると「動いているのに何も起きない」状態になる。今後、進捗系のコールバックは引数から落ちたらTypeScriptの型で弾けるようにしたい。",[18,146],{},[21,148,149],{"id":149},"仕訳インポートのレスポンス検証不足",[26,151,153],{"id":152},"症状-完了と表示されるがデータが入っていない","症状: 「完了」と表示されるがデータが入っていない",[14,155,156],{},"statusCallbackの修正後、インポート処理は進捗表示も含めて最後まで走るようになった。ステータスが「完了」と表示される。しかし会計ソフトA側で仕訳帳を開くとデータが入っていない。",[26,158,160],{"id":159},"chrome-devtoolsで実機検証","Chrome DevToolsで実機検証",[14,162,163],{},"DevToolsのNetworkタブでインポートリクエストのレスポンスを確認した。HTTPステータスは200。ここで「200だから成功」と判定していたのが問題だった。",[14,165,166,167,170],{},"レスポンスのHTMLボディを覗くと、",[39,168,169],{},"alert-danger","クラスのdivが入っている。会計ソフトAのインポートAPIは、バリデーションエラーでもHTTP 200を返し、エラー情報をHTML内のアラートクラスで返す設計だった。",[26,172,174],{"id":173},"修正-html内のアラートクラスを検証","修正: HTML内のアラートクラスを検証",[14,176,177,178,180,181,184],{},"レスポンスHTMLをパースして、",[39,179,169],{},"と",[39,182,183],{},"alert-success","の存在をチェックするようにした。",[186,187,188,194,199],"ul",{},[189,190,191,193],"li",{},[39,192,183],{},"が含まれる → インポート成功",[189,195,196,198],{},[39,197,169],{},"が含まれる → インポート失敗、アラート内のテキストをエラーメッセージとして表示",[189,200,201],{},"どちらもない → 不明な状態としてワーニング",[14,203,204],{},"HTTPステータスだけでなく、レスポンスボディの中身まで見に行く必要がある。REST APIであればステータスコードで判定できるが、フォーム送信ベースのWebアプリはHTMLの中にエラーを埋め込んでくることがある。",[18,206],{},[21,208,210],{"id":209},"繰越処理apiの調査","繰越処理APIの調査",[26,212,213],{"id":213},"背景",[14,215,216],{},"複数事業者の年度末繰越処理を手作業で回すのは面倒で、自動化したかった。Chrome DevToolsで繰越処理の通信を傍受してAPIの構造を把握した。",[26,218,219],{"id":219},"エンドポイント",[48,221,226],{"className":222,"code":224,"language":225},[223],"language-text","POST /term/close?cti={cti}\n","text",[39,227,224],{"__ignoreMap":53},[14,229,230,231,234,235,238],{},"リクエストボディに",[39,232,233],{},"term[journal_lock]=0","を含めると、仕訳制限なしで繰越が実行される。",[39,236,237],{},"cti","は事業者と年度を特定するIDで、既に他のエクスポート処理で取得済みの値がそのまま使える。",[26,240,241],{"id":241},"繰越処理の前提条件",[14,243,244],{},"DevToolsで繰越画面の挙動を追いかけた結果:",[186,246,247,250,253],{},[189,248,249],{},"繰越前に仕訳帳の貸借一致チェックが走る（ここで不一致があると繰越不可）",[189,251,252],{},"繰越実行後、新年度のctiが発行される",[189,254,255],{},"旧年度のctiは閲覧専用になる",[26,257,258],{"id":258},"一括自動化の計画策定",[14,260,261],{},"調査結果をもとに、複数事業者の繰越を一括で自動実行する計画を策定した。",[14,263,264],{},[265,266,267],"strong",{},"フロー:",[269,270,271,274,281,284],"ol",{},[189,272,273],{},"事業者一覧から繰越対象を抽出",[189,275,276,277,280],{},"各事業者のctiを使って",[39,278,279],{},"/term/close","をPOST",[189,282,283],{},"レスポンスのHTML内でエラーがないか検証（インポートと同じパターン）",[189,285,286],{},"成功した事業者と失敗した事業者をレポートとして出力",[14,288,289],{},"Codexレビューにかけて計画を確認。エラーハンドリングの粒度と、繰越失敗時のロールバック手段について指摘を受けた。繰越にはロールバックAPIが存在しないため、実行前の確認ステップを厚めに入れる方針で着地した。",[18,291],{},[21,293,295],{"id":294},"add-taskスキルのjson生成バグ修正","add-taskスキルのJSON生成バグ修正",[26,297,299],{"id":298},"症状-タスク登録が失敗する","症状: タスク登録が失敗する",[14,301,302],{},"計画をGoogleタスクに登録しようとしたら、JSON解析エラーで落ちた。Windows環境固有の問題だった。",[26,304,305],{"id":305},"原因",[14,307,308,309,312,313,316,317,320,321,324],{},"add-taskスキルは内部で",[39,310,311],{},"cat \u003C\u003CHEREDOC","を使ってJSONを生成していた。Windowsのファイルパスに含まれるバックスラッシュ（",[39,314,315],{},"C:\\Users\\...","）が、HEREDOCの中でJSONのエスケープシーケンスと衝突する。",[39,318,319],{},"\\U","が",[39,322,323],{},"\\u","（Unicodeエスケープ）として解釈されてしまう。",[48,326,329],{"className":327,"code":328,"language":225},[223],"# 生成されるJSON（壊れる）\n{\"title\": \"C:\\Users\\numbe\\...\"}  \n# \\U がUnicodeエスケープと衝突\n",[39,330,328],{"__ignoreMap":53},[26,332,334],{"id":333},"修正-python生成方式に変更","修正: Python生成方式に変更",[14,336,337,338,341],{},"HEREDOC方式を捨てて、Pythonの",[39,339,340],{},"json.dumps()","でJSONを生成するように書き換えた。Pythonの文字列リテラルではバックスラッシュが適切にエスケープされるため、Windowsパスが含まれていても壊れない。",[14,343,344],{},"Windows環境でシェルスクリプトからJSONを生成するときは、HEREDOCを避けてプログラミング言語のJSON生成関数を使う方が安全。この手の環境依存バグは、macOSでは再現しないので見つけにくい。",[18,346],{},[21,348,349],{"id":349},"一日の振り返り",[14,351,352],{},"statusCallbackの渡し忘れから始まって、インポートのレスポンス検証、繰越APIの調査まで、1つのバグが次の課題を掘り起こす一日だった。進捗バーが動かない原因を追いかけたら、インポート成功の判定ロジックに穴が見つかり、そこを直したら「次は繰越も自動化したい」という欲が出てきた。",[14,354,355],{},"HTTP 200でもエラーを返すAPIパターンは、フォームベースのWebアプリでは珍しくない。ステータスコードを信じず、レスポンスボディの中身まで検証する習慣を染み込ませたい。",[14,357,358],{},"add-taskのHEREDOCバグは、Windows環境でのシェルスクリプトあるあるとして記憶に刻んでおく。バックスラッシュが2つの文脈で意味を持つ場面では、シェルに任せずプログラミング言語のJSON生成に逃がす。",[360,361,362],"style",{},"html pre.shiki code .sxvE3, html code.shiki .sxvE3{--shiki-default:#A0ADA0;--shiki-dark:#A0ADA0}html pre.shiki code .sHkkW, html code.shiki .sHkkW{--shiki-default:#1E754F;--shiki-dark:#1E754F}html pre.shiki code .senZ8, html code.shiki .senZ8{--shiki-default:#59873A;--shiki-dark:#59873A}html pre.shiki code .shFtX, html code.shiki .shFtX{--shiki-default:#999999;--shiki-dark:#999999}html pre.shiki code .s4oTP, html code.shiki .s4oTP{--shiki-default:#B07D48;--shiki-dark:#B07D48}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":53,"searchDepth":67,"depth":67,"links":364},[365,370,375,381,386],{"id":23,"depth":67,"text":24,"children":366},[367,368,369],{"id":28,"depth":95,"text":29},{"id":35,"depth":95,"text":35},{"id":141,"depth":95,"text":141},{"id":149,"depth":67,"text":149,"children":371},[372,373,374],{"id":152,"depth":95,"text":153},{"id":159,"depth":95,"text":160},{"id":173,"depth":95,"text":174},{"id":209,"depth":67,"text":210,"children":376},[377,378,379,380],{"id":213,"depth":95,"text":213},{"id":219,"depth":95,"text":219},{"id":241,"depth":95,"text":241},{"id":258,"depth":95,"text":258},{"id":294,"depth":67,"text":295,"children":382},[383,384,385],{"id":298,"depth":95,"text":299},{"id":305,"depth":95,"text":305},{"id":333,"depth":95,"text":334},{"id":349,"depth":67,"text":349},"dev","statusCallback未渡しバグの4箇所修正、仕訳インポートのレスポンス検証追加、Chrome DevToolsでの実機調査、繰越処理APIの解析と一括自動化計画、add-taskスキルのJSON生成バグ修正までの記録","md",{},"/chrome-extension-mf-bug-fix","misc-dev",false,"2026-04-01T00:00:00.000Z",{"title":5,"description":388},"2026-04/2026-04-01/chrome-extension-mf-bug-fix",[398,399,400,401,402],"Chrome拡張機能","クラウド会計","バグ修正","API解析","Claude Code","memo",null,"J7PKcBqb0iw9n1zD9jFESAIxZ0bDl5yxUwhT8Ps8vsU",[],"https://log.eurekapu.com/favicon.svg",1775338203490]