Experiment record

Rinnai APIの401 ERR_0010を調査し、乾太くんApps Script収集を復旧した記録

Google Apps Scriptの乾太くん収集処理でRinnai APIのHTTP 401 / ERR_0010が発生した。障害はRinnai認証経路へ局在化でき、保持実装には検証済みの自動認証情報更新経路がなかった。後続記録では認証復旧が確認できるが、具体的な復旧操作は未確定。

概要

Google Apps Scriptで動作していた乾太くん収集処理が、Rinnai APIの**HTTP 401 / ERR_0010**で停止しました。保持された実行ログとコード情報を確認した結果、障害はGoogle Apps Script全体や後段の乾太くん状態処理ではなく、Rinnai APIへ提示した認証情報の経路へ局在化できました。

保持実装はBearerトークンをApps ScriptのScript Propertiesから読み出していましたが、HTTP 401を受けた場合は即時エラー終了しており、検証済みの自動トークン更新と限定再試行は確認できませんでした。

その後の別のトラブルシューティング作業で認証が復旧したとの保持記録があります。ただし、復旧時に行われた具体的な操作を示す保持証拠は残っていません。このため、特定のrefresh endpoint、refresh token、再ログイン方式、ヘッダー修正、トークン有効期限を確認済み事実としては扱いません。

実験の背景

乾太くんの状態・料金関連データをGoogle Apps Scriptで定期収集していたところ、それまで動作していた収集処理がRinnai APIのHTTP 401 / ERR_0010で停止しました。

同じApps Script環境では他の定期収集処理が動作していたため、乾太くん固有の認証経路の問題なのか、収集基盤全体の障害なのかを切り分ける必要がありました。

本実験の目的は、保持されたHTTP応答、実行履歴、スタックトレース、実装情報を使って障害範囲を特定し、同種の停止を長期運用で扱ううえで重要な認証情報ライフサイクル上の課題と未確定事項を明確にすることです。

実験方法

実験対象

実験対象はリンナイ ガス衣類乾燥機「乾太くん」RDT-93です。

型番は2026-08-23に実験使用機から確認しました。この後日の型番確認は、2026-08-14の認証障害そのものを再試験・再検証したものではありません。

実験環境

アプリ通信の観測で得たリクエスト構造をもとに、Google Apps ScriptからRinnai APIを試験する構成でした。概念上のデータ経路は次のとおりです。

iPhone版「乾太くん」アプリ
  → ローカルHTTPS通信観測環境
  → APIリクエスト構造の確認

Google Apps Script
  → Rinnai API request
  → 認証済みリクエスト
  → 乾太くん状態 / 料金データ
  → 収集・集計処理

診断方法

障害調査では、API応答、Apps Script実行履歴、スタックトレース、保持されたrinnaiGet_()周辺の実装情報を比較しました。同じApps Script環境で他の定期収集処理が成功していることも、障害範囲を切り分けるための負の証拠として使用しました。

実験ログ

HTTP 401 / ERR_0010を確認

代表的な応答は次の内容でした。

HTTP 401
errorCode: ERR_0010
message: トークンが無効です

スタックトレースでは次の経路で失敗していました。

rinnaiGet_()
  → pollKantakun_()
  → pollKantakunHourly()

同じApps Script実行履歴では他の定期収集処理が正常終了していました。このため、時間主導トリガーやApps Script環境全体の停止とは切り分けられました。

保持されていた認証実装を確認

認証情報は通常コードへ直接固定せず、Script Propertiesから読み出していました。実際のプロパティキー名は再現上不要なため公開例では省略し、概念上は次の形です。

const token = PropertiesService
  .getScriptProperties()
  .getProperty(TOKEN_PROPERTY_KEY);

この値をBearer認証情報としてAPIリクエストに使用していました。保持されたrinnaiGet_()ではHTTP 401を受けるとエラーを投げて停止しており、確認済みのトークン更新処理や、その後の1回限定再試行は含まれていませんでした。

復旧結果

その後の別のトラブルシューティング作業で認証が復旧したとの保持記録があります。しかし、その作業の具体的な変更履歴は現在保持されているEvidenceに残っていません。

したがって、復旧がBearerトークンの差し替え、refresh tokenによる更新、再ログイン・再認証、ヘッダー修正、その他の実装修正のどれだったかは確定できません。

結論

HTTP 401とRinnai ERR_0010から、今回の障害はRinnai APIの認証経路へ局在化できます。同じApps Script環境の他の定期処理は正常に動作していたため、Apps Script全体や時間主導トリガー全体の停止とする根拠はありませんでした。

保持された実装では、401発生時に検証済みの自動認証情報更新と限定再試行を行う経路は確認できず、エラーで停止していました。このため、長期無人収集で取得済みBearerトークンの無期限有効性を前提とすることはできません。

後続記録では認証が復旧したことは確認できますが、実際に成功した具体的な復旧操作は保持Evidenceから確定できません。したがって、本実験から特定のrefresh endpoint、トークン寿命、refresh tokenの意味、具体的な復旧方式までは結論できません。

証拠区分のまとめ

このExperimentで得られた情報のEvidence Stateは次のとおりです。

記録内容Evidence State本実験での根拠
障害はGoogle Apps Script全体ではなくRinnai API認証経路で発生したVERIFIEDHTTP 401 / ERR_0010と、同時期に他の定期処理が成功していた実行履歴
障害は乾太くんpayload処理やスプレッドシート集計より前段に局在するINFERRED認証ヘルパーrinnaiGet_()で401が発生し、後段へ到達していない
保持実装には401時の検証済み自動トークン更新・限定再試行がなかったOBSERVED保持された401処理が即時エラー終了だった
実際に認証を復旧した具体的操作は保持証拠から確定できないOBSERVED後続の復旧記録はあるが、具体的な変更履歴が残っていない
長期無人収集では認証情報ライフサイクルを明示的に扱う必要があるINFERRED無効認証情報で収集が停止し、既存処理に確認済み更新経路がなかった

各Evidence Stateの意味はEvidence State(証拠状態)を参照してください。

未解決事項

保持Evidenceからは次を確定できません。

これらについては、現在保持されているEvidenceだけでは判断できません。確認には、Rinnaiの正式仕様を確認するか、認証更新時の通信・挙動と成功した復旧手順を直接観測する必要があります。

運用上の示唆

乾太くんデータを継続収集する運用では、HTTP 401などの認証失敗を通常のデータ欠測や一時的APIエラーとは区別して検知し、認証が回復するまで後段の集計処理へ無効なデータを渡さない設計が必要です。

料金反映遅延への対応、推定使用量の計算、他設備データとの集計などは、認証に成功して取得された有効なデータだけを対象にする必要があります。

長期無人収集では、通常のAPIエラーと認証エラーを区別する必要があります。確認済みの認証更新方式が利用できる場合に限って更新を1回実行し、その後の再試行も限定します。更新方法が確認できていない場合、または再試行後も401が続く場合はその収集経路を停止し、認証情報を含まない診断情報を記録する構成が適しています。無制限の再ログインや再試行は避ける必要があります。

実験データについて

元の完全な実行ログや完全な収集ソースコードは公開Artifactとして保持していません。このため、具体的な復旧操作やトークン寿命を後から再解析することには限界があります。

再現に必要なもの

今回の調査方法を理解・再現するために必要なのは、Google Apps Script、Script Properties等の秘密情報ストア、利用権限を持つRinnai API環境、およびHTTPステータス、APIエラー情報、スタックトレースなどを取得・確認できるログ/診断環境です。

ここで必要なのは当時の実行ログそのものではなく、再現試験で同等の診断情報を取得できる環境です。本実験では、購入が必要な専用機材を再現要件としていません。

再現時の注意事項

機微な認証・認可情報や、個体・設置環境を識別し得る情報は、ソースコードや公開ログへ直接記録せず、適切な秘密情報ストアで管理してください。401の切り分け方法と認証ライフサイクル設計は、元の私的情報を共有しなくても再現できます。

機械可読な実験記録

このExperimentの機械可読な正本記録をJSONとして公開しています。

AIEL-2026-0005 experiment.json