約6分で読めます
Culture
【Slack CLI】block_idが衝突してSlackにメッセージを送れない
AI が生成した要約です。正確な内容は本文をご確認ください。
要約を読む
Slackにメッセージを送れなくなっていた問題を解決しました。 その原因は、ブロックの識別子であるblock_idが重複していたからです。 この問題は、Slack CLIを使ってフォームの入力を受け取った際に発生しました。 rich_text型のデータを入力して、それをDataStoreに保存した後、複数のデータをまとめてメッセージを作成しようとしたところ、parameter_validation_failedというエラーが出ていました。 実際に確認したところ、送信しようとしていたブロックのblock_idが同じだったことがわかりました。 Slackの公式ドキュメントによると、block_idは一意でなければなりません。 1つのメッセージやそのやり取りの中で、同じblock_idが使われるとエラーになります。 今回の場合、同じrich_textを入力すると、毎回同じblock_id(例:RlmLN)が生成されるため、入力が同じなら衝突する可能性があります。 解決策として、block_idをすべて削除しました。 インタラクティブな操作がなくても、メッセージを送るだけなら、block_idは必要ありません。 Slackが自動で生成してくれるので、アプリ側でそれを削除するだけでOKです。 コードでdelete演算子を使って、ブロックオブジェクトからblock_idプロパティを消しました。 その結果、メッセージが正常に送れるようになりました。 エラーが起きなくなったのは、block_idの衝突がなくなったからです。 この対応で、Slackに送信できるようになりました。 特に、シンプルなフォーム入力のケースでは、この方法が一番効率的です。 ただし、ボタンやインタラクティブな操作が必要な場合は、アプリ側でblock_idを自分で作って指定する必要があります。 その場合、自動生成に頼らず、一意のIDを割り当てることが重要です。 このように、block_idの使い方を理解することで、Slackのメッセージ送信が安定します。
この記事は KINTOテクノロジーズアドベントカレンダー2024 の5日目の記事です🎅🎄
KINTOテクノロジーズで my route(iOS) を開発しているRyomm a.k.a 幻のbot職人 です。
まなびぃから小ネタです。
ここではSlack CLIの話として書いていますが、内部的にはSlack CLIもSlack APIを使用していますので、Slack APIを直接使用しているケースでも当てはまるかもしれません。
背景
Slack CLIで以下のような処理を行おうとしたとき、なぜかBlock Kitのメッセージが送れないことがありました。
- フォームの入力でrich_text型として値を受け取る
- 値をrich_text型としてDataStoreに保存
- DataStoreから保存したいくつかのrich_text型のデータを取り出して結合し、整形する
postMessageを使って作成したblockを送信する

しかし、parameter_validation_failed というエラーで落ちてしまいました。

原因
送信部分でパラメータ不正のエラーが出ており、送信しようとしていたblockを調べてみると、以下のように block_id が重複していることがわかりました。
[
{
"type": "rich_text",
"block_id": "xdrwH", // <- this
"elements": [
/* ... */
]
}, {
"type": "rich_text",
"block_id": "xdrwH", // <- this
"elements": [
/* ... */
]
}
]
送ろうとしているメッセージの block_id が衝突しているため、Slackにメッセージを送れないようです。
block_id
block_id とは、ブロックの一意の識別子です。
公式ドキュメントには以下のように説明されています。
A unique identifier for a block. If not specified, a block_id will be generated. You can use this block_id when you receive an interaction payload to identify the source of the action. Maximum length for this field is 255 characters. block_id should be unique for each message and each iteration of a message. If a message is updated, use a new block_id.
block_id を指定せずにブロックを作成した場合は、自動的に block_id が生成されます。
主にインタラクティブなやり取りをしたい場合に使用します。例えばボタンが押された際にどのブロックのボタンを押されたのか?などの特定に役立ちます。
1回のメッセージ、もしくはメッセージの反復(=一連の双方向なやり取り)の中で一意である必要があります。
また、メッセージが更新された際には新しい block_id を使用します。
今回のようにフォームでの入力の場合、受け取ったrich_textに含まれる block_id は自動生成されたものになります。
さらに、冒頭の処理では入力で受け取るrich_textは別々のメッセージとして受け取っているため、 block_id も重複している可能性があります。
実際に今回の問題は block_id が衝突していることで起こりました。
ここで一句
なぜなのか 自動生成 信じてた 衝突するよ block_id
自動生成されたblock_idはUUID的な簡単には衝突しないものだと信じていたのに、衝突したなぁ...という唖然とした気持ちが表れていますね。
これは私の推測ですが、Slack側が自動生成する block_id はブロックの内容をもとに作られていると思われます。
試しに全く同じ入力を行うと、全く同じ block_id が取得できます。

rich_textにhogeと入力する
→ 毎回 RlmLN というblock_idが生成される
{
"type": "rich_text",
"block_id": "RlmLN",
"elements": [
{
"type": "rich_text_section",
"elements": [
{
"text": "hoge",
"type": "text"
}
]
}
]
}
このため、全く同じ入力がある可能性がある場合、同じくらい block_id が衝突する可能性もあると考えると良いでしょう。
解決策
さて、いくつかのブロックを結合して1つのメッセージとしてSlackに送りたいとき、メッセージ内のそれぞれのblock_idは一意にする必要があります。
インタラクティブな動作を行わない場合、 block_id を保持する必要性はあまりないので削除してしまうのが一番シンプルな解決策です。
block_id が指定されていない場合はSlack側が自動で生成してくれるため、 block_id を削除したまま送信します。
これは整形を行なっているメソッドの一部です。delete演算子でオブジェクトからblock_idプロパティを削除しています。
// client.apps.datastore.query で取得した結果のitemsが引数eventに入る
// 参考: https://api.slack.com/methods/apps.datastore.query#examples
function eventMessage(event) {
// ...
event.description.forEach((description) => {
if (description.block_id) {
delete description.block_id // 🐈❗️
}
message.push(description)
})
// ...
}
これで block_id の衝突を気にせずメッセージを送ることができるようになりました!
ただし、インタラクティブなやり取りをしたいときには、オブジェクトから block_id を削除するのは良い方法ではないです。
その場合は、送信時にアプリ側で block_id を作成して割り当てると良いと思います。
おわりに
block_id が衝突してメッセージが送れないはなしでした!
関連記事 | Related Posts
We are hiring!
Follow Us
KINTOテクノロジーズの最新情報をSNSで発信中!イベント・テックブログ更新情報もお届けします。
