スカラータグのパラメータがレビューキューに受理されると、承認時にHTTP 500が発生

自己ホスト型サイトでのキューイングされたトピックの承認が HTTP 500 エラーで失敗しました。原因は、キューイングされたレコードに payload.tags = "macos"(文字列)が含まれていたことです。この不正な値はすでに POST /posts によって受け入れられていました。

クライアントはタグの配列を送信すべきであると理解しています。私が報告している問題は、無効なスカラー値がレビューキューに受け入れられ、モデレーターが投稿を承認する際に初めて失敗するという点です。

バージョン: 2026.10.0-latest, コミット 3f2bf92368c78a7fa9a755f3d046adf35dd4459b

インシデントからの証拠

この投稿は approve_post_count のため承認が必要でした。

2026-10-22 13:37:52 UTC に、元の Rails リクエストパラメータにはすでに以下が含まれていました:

"tags" => "macos"

リクエストは POST /posts であり、対応するアクセスログには HTTP 200 が記録されていました。送信されたパラメータ名は title、raw、category、および tags でした。

保留中のレビュー可能オブジェクト(Reviewable)を読み取った結果は以下の通りでした:

{
  "type": "ReviewableQueuedPost",
  "status": 0,
  "version": 0,
  "topic_id": null,
  "payload": {
    "tags": "macos"
  }
}

これは関連フィールドの抜粋であり、タイトル、本文、ユーザー情報は省略されています。レビュー UI では、タグが5つの独立した文字として表示されていました:m、a、c、o、s。

「承認」をクリックすると、以下の例外が発生しました(ログに5つのグループ化された発生箇所があります):

NoMethodError (undefined method '-' for an instance of String)
lib/discourse_tagging.rb:932:in 'DiscourseTagging.tags_for_saving'
lib/discourse_tagging.rb:43:in 'DiscourseTagging.tag_topic_by_names'
lib/discourse_tagging.rb:30:in 'DiscourseTagging.tag_topic'
lib/topic_creator.rb:228:in 'TopicCreator#setup_tags'
lib/topic_creator.rb:60:in 'TopicCreator#create'
lib/post_creator.rb:519:in 'PostCreator#create_topic'
lib/post_creator.rb:209:in 'block in PostCreator#create'
lib/post_creator.rb:419:in 'block in PostCreator#transaction'
lib/post_creator.rb:419:in 'PostCreator#transaction'
lib/post_creator.rb:207:in 'PostCreator#create'
app/models/reviewable_queued_post.rb:110:in 'ReviewableQueuedPost#perform_approve_post'
app/models/reviewable.rb:433:in 'Kernel#public_send'
app/models/reviewable.rb:433:in 'block in Reviewable#perform'
app/models/reviewable.rb:431:in 'Reviewable#perform'
app/controllers/reviewables_controller.rb:287:in 'ReviewablesController#perform'

関連コード

上記のコミット時点の実行中コンテナ内で確認されたコードパスは以下の通りです:

  • PostsController#create_params は params.permit(tags: %i[id name]) を呼び出しますが、返されたフィルタリング済みのパラメータを使用していません。その後、result[f] = params[f] で元の値を代入しています。
  • NewPostManager#enqueue は @args[:tags] を直接レビュー可能オブジェクトのペイロードにコピーします。
  • ReviewableQueuedPost#create_options は、値がすでに配列である場合のみタグを変換し、スカラー文字列はそのままで残します。
  • その後、DiscourseTagging.tags_for_saving が、承認するユーザーがタグを作成できる場合に tags_arg - tag_names を評価するため、文字列に対して例外を発生させます。

期待される動作

レビュー可能オブジェクトを作成する前に、スカラーの tags パラメータを明確な検証エラーで拒否するか、それが意図された互換性動作である場合は正規化してください。既存の不正なレビュー可能オブジェクトも、モデレーション中に未処理の 500 エラーを引き起こすのではなく、適切に失敗すべきです。

回避策とこの報告書の限界

レビュー可能オブジェクトを編集し、古いタグを削除して、既存の macos タグを選択して保存することで、payload.tags がタグオブジェクトの配列に変更されました。読み戻しにより、バージョン 1、依然として保留中であること、UI に再び1つのタグが表示されていることが確認されました。その変更後の承認のリトライはまだ行っていません。

元の送信者のクライアントは不明です。この報告書は、ネイティブコンポーザーがスカラータグを生成することを証明するものではありません。実際のリクエスト、保存されたレビュー可能オブジェクト、例外、および検査されたコードに基づいています。クリーンインストール環境での個別の再現は行っていません。

開発用の再現のために、テストすべきパスは以下の通りです:非スタッフユーザーの投稿に対して承認を必須にし、スカラーの tags: "macos" とそれ以外の有効なフィールドを含む POST /posts を送信し、その後管理者として結果として生じたキューイングされた投稿を承認します。

同じ文字列減算例外に関する古い API 上の議論があります。この報告書では、無効な値がレビューキューに受け入れられ、後に承認を破綻させることに焦点を当てています。