JavaScript
Node.js
Slack

@slack/client 4.0.0 の IncomingWebhook sendとレスポンスエラー(ParseError: Unexpected token o in JSON at position 0)

バージョン

@slack/client 4.0.0
slackapi/node-slack-sdk: Slack Developer Kit for Node.js

症状

2つ。

1つ目は

IncomingWebhooksendメソッドに、
メッセージのみのstringを渡すと
payload.text = message;
TypeError: Cannot set property 'text' of undefined

bot名なども指定できるオブジェクトを渡すと
payload = Object.assign(payload, message);
TypeError: Cannot convert undefined or null to object

と引数関連。

これを回避すると、2つ目に

Error: { ParseError: Unexpected token o in JSON at position 0 in "https://hooks.slack.com/services/~"
got\index.js:366:15

とレスポンスの扱いエラー(送信は成功している。)
軽くググるとこちらはすでにJSONのものを再度JSONにしようとしている?(token o はObjectのoらしい)

Github上では修正済み

ググってもそれらしい情報がなかったので、GitHubのIssuesから検索したらバグとして出ていた。

JSON.parse(res.body) in got/index.js:335:15 throwing a ParseError for statusCode: 200 · Issue #477 · slackapi/node-slack-sdk

(内容は読んでいない)

症状1の原因としてはデフォルトで持つペイロードの初期値を決めてなかったので、undefinedを操作しようとしてエラー。

症状2はgotに最初からjsonだと教えていたのでエラー?こちらはよくわからない。

一時回避方法

コミット済みとはいえ、まだリリースされていないので、npmの更新ではダメ。
手動で修正する。

症状1は呼び出し側のワークアラウンドで対応可能。

デフォルト値が指定されていないなら、引数で仮のデフォルト値を渡せばいい。

constructor(url: string, defaults: IncomingWebhookDefaultArguments)
利用側スクリプト.js
const { IncomingWebhook } = require('@slack/client');
const url = 'https://hooks.slack.com/services/~'
//const webhook = new IncomingWebhook(url);
// ↓ デフォルト値を空のオブジェクトにしてやる。
const webhook = new IncomingWebhook(url, {});

本家の修正も

constructor(url: string, defaults: IncomingWebhookDefaultArguments = {}) {

とデフォルト引数を付ける修正。

なので、
@slack/client/dist/IncomingWebhook.js
のconstructorにちゃちゃっと= {}を付けるほうがいいかも。


症状2は内部のことなのでコミット参照してコピペする。
tsではなくてdistのコードへ。
(ts関係ない修正でよかった…)

(31行目before)@slack/client/dist/IncomingWebhook.js
        const implementation = () => {
            return got.post(this.url, {
                json: true,
                body: payload,
                retries: 0,
            });
        };
(31行目after)@slack/client/dist/IncomingWebhook.js
        const implementation = () => got.post(this.url, {
            body: JSON.stringify(payload),
            retries: 0,
        }).then(() => {
            return;
        });

(ただしsendのコールバックのレスポンスがundefinedになるっぽくて、エラーにはならないが応答が取れてなさそう。)


4.0.0のリリースが2018/3/9で、私が(初めて)インストールしたのもその当日という、リリース直後のバグを踏んだ形でした。不運!
しかしわずか9時間後にはIssueで報告されているのは助かった!