kintone の既存レコードに潜む「制約違反データ」を一括検出する Chrome 拡張を作った
はじめに
kintone アプリを運用していると、こんな経験はありませんか?
- 運用開始後にフィールドを必須に変更した
- あとから数値フィールドに上限・下限を設定した
- あとから文字列フィールドに文字数制限を追加した
kintone のフィールド制約はレコードの新規作成・編集時にしか働きません。そのため、設定変更より前に登録された既存レコードには、制約に違反したままのデータが残り続けます。しかも kintone 標準機能では、こうした「隠れ違反データ」を一覧する手段がありません。
この隠れ違反データ、普段は静かにしているのですが、レコードを一括更新するタイミングで牙をむきます。更新時には現在の制約でバリデーションが働くため、たとえば次のような処理が違反レコードに当たると、思わぬエラーで失敗します。
- 一括更新系のプラグインや連携サービスによる更新処理
- CSV ファイルの読み込みによる既存レコードの一括更新
- REST API(
PUT /k/v1/records.json)を使った自作カスタマイズやバッチ処理
厄介なのは、更新しようとした値ではなく、触っていない既存フィールドの違反が原因でもエラーになることです。「プラグインの設定は正しいのに一部のレコードだけ更新に失敗する」という現象の裏に、こうした違反データが潜んでいることがよくあります。エラーメッセージだけでは原因のレコードやフィールドを特定しづらく、調査に時間を取られがちです。
そこで、開いているアプリの全レコードを一括チェックして制約違反を洗い出す Chrome 拡張機能 kintone レコード制約チェッカー を作りました。
📦 リポジトリ: https://github.com/rex0220/kintone-constraint-checker (MIT License)
できること
ツールバーの拡張機能アイコンをクリックするだけで、開いているアプリの全レコードをチェックします。
| チェック項目 | 内容 |
|---|---|
| 必須チェック | 必須フィールドが空のレコードを検出(全フィールドタイプ対象) |
| 数値上下限チェック | 数値フィールドの下限値未満・上限値超過を検出 |
| 文字数制限チェック | 文字列(1行)の最小・最大文字数違反を検出 |
さらに、こんな特徴があります。
-
テーブル(サブテーブル)内のフィールドにも対応 — 行番号付きでレポートします(例:
明細テーブル 3行目「単価」) - 結果はダイアログに先頭 50 件まで表示し、全件は CSV でダウンロードできます
- CSV は UTF-8 BOM 付き・CRLF なので、Excel でそのまま開いても文字化けしません
- 列構成: レコードID($id) / フィールド / エラー内容 / 現在の状態
- 日英 2 か国語対応 — kintone のユーザー言語設定が日本語なら日本語、それ以外は英語で表示
- チェックは閲覧のみで、レコードの更新は一切行いません
対応ドメインは https://*.cybozu.com / https://*.cybozu.cn / https://*.kintone.com です。
インストール
Chrome ウェブストアには公開していないため、デベロッパーモードで読み込みます。
- リポジトリをクローン(または ZIP でダウンロード)してローカルに配置する
- Chrome で
chrome://extensionsを開く - 右上の「デベロッパーモード」をオンにする
- 「パッケージ化されていない拡張機能を読み込む」でフォルダーを選択する
使い方
- kintone のアプリ画面(レコード一覧や詳細)を開く
- ツールバーの拡張機能アイコンをクリックする
- 確認ダイアログで「チェックを開始する」を押す
- チェック完了後、結果ダイアログで違反内容を確認する
- 違反が 1 件以上ある場合は「CSVをダウンロード」ボタンで全件を保存できます
開始確認ダイアログ
アイコンをクリックすると、対象アプリの ID を示した確認ダイアログが表示されます。
結果ダイアログ
違反がなければ「🎉 チェック完了!データは綺麗です」、あれば「⚠️ 制約エラーを検出しました」として、レコードID・フィールド名・エラー内容・現在の値がリストアップされます。
仕組み
構成はシンプルで、実質 2 ファイルです。
| ファイル | 役割 |
|---|---|
manifest.json |
Manifest V3 定義。名前・説明は _locales で日英切り替え |
background.js |
Service Worker。アイコンクリック時に checker.js をページの MAIN world に注入 |
checker.js |
チェック本体。kintone REST API でフィールド定義と全レコードを取得して検査し、結果を表示 |
以下、実装上のポイントを紹介します。
ポイント1: MAIN world への注入でページの kintone オブジェクトを使う
Chrome 拡張のコンテンツスクリプトは通常、ページとは分離された ISOLATED world で動くため、ページ側の kintone オブジェクトにアクセスできません。この拡張では chrome.scripting.executeScript の world: "MAIN" を指定して、ページ本体と同じコンテキストでスクリプトを実行しています。
chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target: { tabId: tab.id },
files: ["checker.js"],
world: "MAIN" // ページ側の kintone オブジェクトにアクセスするため
});
});
これにより kintone.api() がそのまま使えるので、認証は開いているブラウザセッションをそのまま利用できます。API トークンの発行や設定は不要で、外部へのデータ送信も一切ありません。
ポイント2: $id カーソル方式で offset 上限 10,000 件を回避
kintone REST API の offset には 10,000 件の上限があります。レコード数の多いアプリでも全件取得できるよう、$id をカーソルにしたページングで 500 件ずつ取得しています。
let allRecords = [];
let lastRecordId = 0;
while (true) {
const query = `$id > ${lastRecordId} order by $id asc limit 500`;
const resp = await kintone.api(kintone.api.url('/k/v1/records.json', true), 'GET', {
app: appId,
query: query
});
if (resp.records.length === 0) break;
allRecords = allRecords.concat(resp.records);
lastRecordId = resp.records[resp.records.length - 1].$id.value;
}
レコードの識別に「レコード番号」ではなく $id を使っているのは、アプリコード設定の影響を受けないためです。
ポイント3: フィールド定義とレコード値の突き合わせ
/k/v1/app/form/fields.json で取得したフィールド定義(required / minValue / maxValue / minLength / maxLength)と各レコードの値を突き合わせてチェックします。
kintone 本体の挙動に合わせて、空値のフィールドは必須チェックのみ行い、数値・文字数チェックはスキップしています(空を許容しつつ、入力があれば範囲を検証するという kintone の仕様に準拠)。
テーブル(SUBTABLE)は行ごとに内部フィールド定義と突き合わせ、テーブル名 N行目「フィールド名」 の形式でレポートします。
ポイント4: Excel で開ける CSV 出力
エラー全件の CSV は UTF-8 の BOM 付き・CRLF 改行で生成しています。これがないと Excel でダブルクリックしたときに文字化けするやつです。
const blob = new Blob(['\uFEFF' + lines.join('\r\n')], { type: 'text/csv;charset=utf-8;' });
注意事項
- チェックは閲覧のみで、レコードの更新は行いません
- 実行ユーザーに閲覧権限があるレコード・フィールドだけがチェック対象です。権限外のデータは検出できません
- レコード件数が多いアプリでは取得に時間がかかります(REST API の呼び出しは 500 件ごとに 1 回)
- チェック対象外の制約: 重複禁止、正規表現などカスタマイズによる独自バリデーション、添付ファイルサイズ 等
おわりに
「フォームの制約は過去のデータには効かない」という kintone の仕様は意外と見落とされがちで、アプリの設定変更を重ねるほど違反データは静かに溜まっていきます。プラグインや CSV 読み込みで一括更新する前の事前チェックとして、データクレンジングの前段として、あるいは定期的な運用品質チェックとして使ってもらえたら嬉しいです。

