yuya373 / emacs-slack

slack client for emacs
1.11k stars 117 forks source link

Some channels simply don't load #498

Open nicklan opened 4 years ago

nicklan commented 4 years ago

Describe the bug For some channels, when I do slack-channel-select, I'll get the "No Message in [channel], fetching from server..." message, and then... nothing.

Subsequent times I try I get a message saying: Unbound slot: slack-reply-broadcast-message, "#<slack-reply-broadcast-message slack-reply-broadcast-message>", user, oref.

I haven't managed to tie it down to anything in particular about the channel, so sorry for the somewhat vague description. Let me know if there's more debugging info that could help you.

To Reproduce sadly I don't know how to reliably reproduce.

Environment:

yuya373 commented 4 years ago
duncan-bayne commented 4 years ago

I can reproduce this with a few channels on my work Slack - ironically, the #emacs channel is one :joy:

There's no particular error displayed, just a notification that it's downloading messages, followed by silent failure. Emacs goes to ~ 100% CPU usage (on a single core) during that time, and locks up.

The following *Messages* are generated:

[2020-04-21 23:13:21] [debug] [cogent] Authorization Finished
[2020-04-21 23:13:22] [debug] [Cogent] WebSocket on-open
[2020-04-21 23:13:23] [info] [Cogent] Slack Websocket Is Ready!
[2020-04-21 23:13:23] [info] [Cogent] Slack Command List Updated
Failed to request slack-dnd-status-team-info: no_users_provided
[2020-04-21 23:13:29] [info] [Cogent] Slack Channel List Updated
[2020-04-21 23:13:29] [info] [Cogent] Slack Group List Updated
[2020-04-21 23:13:29] [info] [Cogent] Slack Im List Updated
[2020-04-21 23:13:30] [info] [Cogent] Fetching users... [60/96]
[2020-04-21 23:13:31] [info] [Cogent] Fetching users... [90/96]
[2020-04-21 23:16:37] [error] [Cogent] REQUEST FAILED. URL: "https://slack.com/api/conversations.view", ...snip... :response_metadata (:next_cursor "REDACTED"))

To my knowledge, no bots are running on this channel.

Very happy to help you debug this in any way I can, as I'm hoping to switch over from the official client to Emacs as soon as possible :)

ag91 commented 3 years ago

In my case the channel that has this behavior does not return a timestamp in the parameters. A good channel: [2020-09-14 16:54:09] [trace] REQUEST FINISHED. URL: "https://slack.com/api/conversations.mark", PARAMS: (("channel" . "SOMEID") ("ts" . "1600095247.156900")), DATA: (:ok t) The bad channel: [2020-09-14 16:54:47] [trace] REQUEST FINISHED. URL: "https://slack.com/api/conversations.join", PARAMS: (("channel" . "SOMEOTHERID")), DATA: (:ok t :channel ... The bit weird is the ts parameter that seems absent. Is that valid also for you @duncan-bayne ? Would that explain the issue @yuya373 ?

Never mind I looked at the logs wrongly.

dyroffk commented 3 years ago

I experienced this issue on a few of our slack channels and have been trying to narrow it down.

Enabling debug-on-error yields the following stack trace

Debugger entered--Lisp error: (invalid-slot-type slack-image-block-element image-height number nil)
  signal(invalid-slot-type (slack-image-block-element image-height number nil))
  eieio--validate-slot-value(#s(eieio--class :name slack-image-block-element :docstring nil :parents (#s(eieio--class :name slack-block-element :docstring nil :parents nil :slots [#s(cl-slot-descriptor :name type :initform unbound :type string :props nil) #s(cl-slot-descriptor :name action-id :initform "" :type string :props nil) #s(cl-slot-descriptor :name confirm :initform nil :type (or null slack-confirmation-dialog-message-composition-object) :props nil) #s(cl-slot-descriptor :name payload :initform nil :type t :props nil)] :index-table #<hash-table eq 4/65 0x1560b2e1560d> :children (slack-date-picker-block-element slack-overflow-menu-block-element slack-select-block-element slack-button-block-element slack-image-block-element) :initarg-tuples ((:type . type) (:action_id . action-id) (:confirm . confirm) (:payload . payload)) :class-slots [] :class-allocation-values [] :default-object-cache #<slack-block-element slack-block-element-1560b601c614> :options (:custom-groups nil))) :slots [#s(cl-slot-descriptor :name type :initform "image" :type string :props nil) #s(cl-slot-descriptor :name action-id :initform "" :type string :props nil) #s(cl-slot-descriptor :name confirm :initform nil :type (or null slack-confirmation-dialog-message-composition-object) :props nil) #s(cl-slot-descriptor :name payload :initform nil :type t :props nil) #s(cl-slot-descriptor :name image-url :initform unbound :type string :props nil) #s(cl-slot-descriptor :name alt-text :initform unbound :type string :props nil) #s(cl-slot-descriptor :name image-height :initform unbound :type number :props nil) #s(cl-slot-descriptor :name image-width :initform unbound :type number :props nil) #s(cl-slot-descriptor :name image-bytes :initform unbound :type number :props nil)] :index-table #<hash-table eq 9/65 0x1560b43e2ef1> :children nil :initarg-tuples ((:type . type) (:action_id . action-id) (:confirm . confirm) (:payload . payload) (:image_url . image-url) (:alt_text . alt-text) (:image_height . image-height) (:image_width . image-width) (:image_bytes . image-bytes)) :class-slots [] :class-allocation-values [] :default-object-cache #<slack-image-block-element slack-image-block-element-1560b515ba6c> :options (:custom-groups nil)) 7 nil image-height)
  eieio-oset(#<slack-image-block-element slack-image-block-element-1560b4743978> image-height nil)
  #f(compiled-function (obj slots) "Set slots of OBJ with SLOTS which is a list of name/value pairs.\nCalled from the constructor routine." #<bytecode 0x1560b264f2d5>)(#<slack-image-block-element slack-image-block-element-1560b4743978> (:image_url "https://a.slack-edge.com/dc483/img/plugins/giphy/s..." :alt_text "giphy logo" :image_height nil :image_width nil :image_bytes nil))
  apply(#f(compiled-function (obj slots) "Set slots of OBJ with SLOTS which is a list of name/value pairs.\nCalled from the constructor routine." #<bytecode 0x1560b264f2d5>) #<slack-image-block-element slack-image-block-element-1560b4743978> (:image_url "https://a.slack-edge.com/dc483/img/plugins/giphy/s..." :alt_text "giphy logo" :image_height nil :image_width nil :image_bytes nil))
  shared-initialize(#<slack-image-block-element slack-image-block-element-1560b4743978> (:image_url "https://a.slack-edge.com/dc483/img/plugins/giphy/s..." :alt_text "giphy logo" :image_height nil :image_width nil :image_bytes nil))
  #f(compiled-function (this &optional slots) "Construct the new object THIS based on SLOTS.\nSLOTS is a tagged list where odd numbered elements are tags, and\neven numbered elements are the values to store in the tagged slot.\nIf you overload the `initialize-instance', there you will need to\ncall `shared-initialize' yourself, or you can call `call-next-method'\nto have this constructor called automatically.  If these steps are\nnot taken, then new objects of your class will not have their values\ndynamically set from SLOTS." #<bytecode 0x1560b264f301>)(#<slack-image-block-element slack-image-block-element-1560b4743978> (:image_url "https://a.slack-edge.com/dc483/img/plugins/giphy/s..." :alt_text "giphy logo" :image_height nil :image_width nil :image_bytes nil))
  apply(#f(compiled-function (this &optional slots) "Construct the new object THIS based on SLOTS.\nSLOTS is a tagged list where odd numbered elements are tags, and\neven numbered elements are the values to store in the tagged slot.\nIf you overload the `initialize-instance', there you will need to\ncall `shared-initialize' yourself, or you can call `call-next-method'\nto have this constructor called automatically.  If these steps are\nnot taken, then new objects of your class will not have their values\ndynamically set from SLOTS." #<bytecode 0x1560b264f301>) #<slack-image-block-element slack-image-block-element-1560b4743978> (:image_url "https://a.slack-edge.com/dc483/img/plugins/giphy/s..." :alt_text "giphy logo" :image_height nil :image_width nil :image_bytes nil))
  initialize-instance(#<slack-image-block-element slack-image-block-element-1560b4743978> (:image_url "https://a.slack-edge.com/dc483/img/plugins/giphy/s..." :alt_text "giphy logo" :image_height nil :image_width nil :image_bytes nil))
  #f(compiled-function (class &rest slots) "Default constructor for CLASS `eieio-default-superclass'.\nSLOTS are the initialization slots used by `initialize-instance'.\nThis static method is called when an object is constructed.\nIt allocates the vector used to represent an EIEIO object, and then\ncalls `initialize-instance' on that object." #<bytecode 0x1560b264f2b9>)(slack-image-block-element :image_url "https://a.slack-edge.com/dc483/img/plugins/giphy/s..." :alt_text "giphy logo" :image_height nil :image_width nil :image_bytes nil)
  apply(#f(compiled-function (class &rest slots) "Default constructor for CLASS `eieio-default-superclass'.\nSLOTS are the initialization slots used by `initialize-instance'.\nThis static method is called when an object is constructed.\nIt allocates the vector used to represent an EIEIO object, and then\ncalls `initialize-instance' on that object." #<bytecode 0x1560b264f2b9>) slack-image-block-element (:image_url "https://a.slack-edge.com/dc483/img/plugins/giphy/s..." :alt_text "giphy logo" :image_height nil :image_width nil :image_bytes nil))
  make-instance(slack-image-block-element :image_url "https://a.slack-edge.com/dc483/img/plugins/giphy/s..." :alt_text "giphy logo" :image_height nil :image_width nil :image_bytes nil)
  slack-create-image-block-element((:type "image" :image_url "https://a.slack-edge.com/dc483/img/plugins/giphy/s..." :alt_text "giphy logo"))

<--SNIP-->

As far as I can tell, at least for our slack team, this is primarily caused by giphy bot when slack-create-image-block-element is called with a subset of the expected arguments in the payload e.g.

(:type image :image_url https://a.slack-edge.com/dc483/img/plugins/giphy/service_32.png :alt_text giphy logo)

This was nested in a context block:

 (:type "context" :block_id "F0k" :elements ((:type "image" :image_url "https://a.slack-edge.com/dc483/img/plugins/giphy/s..." :alt_text "giphy logo") (:type "mrkdwn" :text "Posted using /giphy" :verbatim :json-false)))

I hope that helps. I can reliably reproduce the issue if there's anything else I can do to help

I ended up getting past the issue by locally commenting out the rendering of context blocks because that's where the problem seemed to be isolated for me

For more context, it appears this was a message in a thread posted using /giphy

dyroffk commented 3 years ago

A slightly cleaner way to bypass this issue I tried that seems to work: https://github.com/yuya373/emacs-slack/blob/master/slack-block.el#L714-L720

modified   slack-block.el
@@ -715,9 +715,9 @@
   (make-instance 'slack-image-block-element
                  :image_url (plist-get payload :image_url)
                  :alt_text (plist-get payload :alt_text)
-                 :image_height (plist-get payload :image_height)
-                 :image_width (plist-get payload :image_width)
-                 :image_bytes (plist-get payload :image_bytes)))
+                 :image_height (or (plist-get payload :image_height) 0)
+                 :image_width (or (plist-get payload :image_width) 0)
+                 :image_bytes (or (plist-get payload :image_bytes) 0)))

It's unclear why these blocks seem to be coming in with no height, width or bytes, but this at least prevents it from blowing up with the above invalid-slot-type

Not sure if this is a good long-term solution, since ideally the image would be rendered, but it's better than the current behavior of failing to load the channel

dyroffk commented 3 years ago

Looks like https://github.com/yuya373/emacs-slack/pull/532 is also related to this and a possible solution

dyroffk commented 3 years ago

I tested and the solution in #532 successfully rendered the image unlike my hack above defaulting to 0 FYI

ag91 commented 3 years ago

thanks to look into this @dyroffk, at least we have a patch now! Very grateful for your time