Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Empty "state" Value in AppHomeOpened Event Causes Parsing Error #943

Open
HunterL opened this issue Jun 10, 2021 · 7 comments
Open

Empty "state" Value in AppHomeOpened Event Causes Parsing Error #943

HunterL opened this issue Jun 10, 2021 · 7 comments

Comments

@HunterL
Copy link

HunterL commented Jun 10, 2021

What happened

  • Published a home view with some text and a simple static_select element
  • Every subsequent "AppHomeOpened" event has been parsed as "err_bad_message"

&{Cause:parsing Events API event: EventsAPI Error parsing inner event: unmarshalling_error, json: cannot unmarshal array into Go struct field ViewState.view.state.values of type map[string]map[string]slack.BlockAction

The client is recieving the following JSON (as part of a larger event...):

"state": {
    "values": []
},

And attempting to marshal it into

type ViewState struct {
	Values map[string]map[string]BlockAction `json:"values"`
}

Versions

  • Go: 1.15.5
  • slack-go/slack: 0.9.1

Work Around

Thought I should add an edit on how we're working around this until there is clarity from Slack and we can merge a fix into slack-go

  1. Add a struct to help us pull out the payload and envelope ID
// HomeEvent is a helper struct for recovery from err bad message
type HomeEvent struct {
	Envelope string                     `json:"envelope_id"`
	Payload  json.RawMessage `json:"payload"`
}
  1. Pull out the payload, fix the brackets causing an issue, stuff it back into an event, push back into the client channel
case socketmode.EventTypeErrorBadMessage:
	/*
		We do some handling here to attempt to recover the event from a known issue with "AppHomeOpened"
		If we fail to recover the assumption is that the bad event was for a legitimate reason and not
		an internal issue with slack-go
	*/
	var e *socketmode.ErrorBadMessage
	var ok bool
	if e, ok = event.Data.(*socketmode.ErrorBadMessage); !ok {
		log.Printf("Bad Message Not Cast: %+v", event)
		continue
	}
	var rawBytes []byte
	if rawBytes, err = e.Message.MarshalJSON(); err != nil {
		log.Printf("Bad Message Not Marshalled. Err: %+v\n Event: %+v", err, event)
		continue
	}

	/*
		This line replaces `"state":{"values":[]}` with `"state":{"values":{}}`
		The latter is parsed correctly by slack-go while the former is what kicks off the "ErrorBadMessage"
		event in the first place. It is, unfortunately, the best way to fix this behavior until there is
		clarification from slack on intended return values and a fix is merged into slack-go
	*/
	rawMessage := bytes.Replace(rawBytes, []byte{34, 115, 116, 97, 116, 101, 34, 58, 123, 34, 118, 97, 108, 117, 101, 115, 34, 58, 91, 93, 125}, []byte{34, 115, 116, 97, 116, 101, 34, 58, 123, 34, 118, 97, 108, 117, 101, 115, 34, 58, 123, 125, 125}, 1)
	var hE HomeEvent
	if err := json.Unmarshal(rawMessage, &hE); err != nil {
		log.Printf("Raw Message Not Marshalled: %s", err)
                 continue
	}

	// Parse the raw json payload without verifying the token as it will fail otherwise
	var newEvent slackevents.EventsAPIEvent
	if newEvent, err = slackevents.ParseEvent(hE.Payload, slackevents.OptionNoVerifyToken()); err != nil {
		log.Printf("Bad Message Not Parsed. Err: %+v\n Inner JSON: %+v", err, rawMessage)
		continue
	}

	// Plug all of our parts into an event
	fabEvent := socketmode.Event{
		Type: socketmode.EventTypeEventsAPI,
		Data: newEvent,
		Request: &socketmode.Request{ //  we need to attach the envelope ID for the request to Ack
			Type:       "events_api",
			EnvelopeID: hE.Envelope,
		},
	}
	h.Client.Events <- fabEvent

edit: Realized there is some ambiguity on "h.Client.Events". The "h.Client" is of type *socketmode.Client

@HunterL
Copy link
Author

HunterL commented Jun 14, 2021

Dug into this some more, the issue seems that slack-go expects the empty state be a nil JSON obj and not an empty JSON array.

"state": {
    "values": {} // <-- What we expect  || What we get --> // "values":[]
},

You can test this by modifying slackevents/parsers.go and replacing the bytes of the raw JSON before it gets marshaled

func parseInnerEvent(e *EventsAPICallbackEvent) (EventsAPIEvent, error) {
	iE := &slack.Event{}
	rawBytes, _ := e.InnerEvent.MarshalJSON()
	rawInnerJSON := bytes.Replace(rawBytes, []byte{34, 115, 116, 97, 116, 101, 34, 58, 123, 34, 118, 97, 108, 117, 101, 115, 34, 58, 91, 93, 125}, []byte{34, 115, 116, 97, 116, 101, 34, 58, 123, 34, 118, 97, 108, 117, 101, 115, 34, 58, 123, 125, 125}, 1)
...

@HunterL
Copy link
Author

HunterL commented Jun 14, 2021

Sent an email to slack support on this one because between what I'm receiving in responses, what they document, and what their API tester returns - the expected return behavior (nil json obj or empty array) is unclear. Will update once cleaned up.

@HunterL
Copy link
Author

HunterL commented Jun 18, 2021

Heard back from Slack support, it is a bug.

I'm afraid we have a bug with apps that have Socket Mode enabled where the state value in the app_home_opened event payload returns a values array instead of an object.

Please note that it may take a bit of time for the team to track down the source of this problem which is needed before we can look into how to get this issue resolved.

My apologies for the trouble, and that I don't have better news for you on this at the moment. We appreciate your patience on this. Please don't hesitate to reach out if there's anything else that I can help with in the meantime.

@kanata2
Copy link
Member

kanata2 commented Jun 20, 2021

@HunterL Thank you for your investigation.

@HunterL
Copy link
Author

HunterL commented Oct 25, 2021

Received a note from Slack support that this issue has been fixed.

@HunterL HunterL closed this as completed Oct 25, 2021
@derekritchison
Copy link

Hey there- I am actually seeing this exact behavior, and it started happening out of nowhere mid-testing earlier this morning. Up until recently I had been receiving full view_submission responses with view.state.values containing my submitted text responses. But suddenly I started receiving:

"state": {
"values": []
},

I am incredibly confused because I did not change anything in my original views.open modal. The response JSON... just changed?

Happy to share any additional info to help troubleshoot what could have happened here.

@kanata2
Copy link
Member

kanata2 commented Aug 10, 2022

I re-open this issue for investigation. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants