Question JS breaks after language switch (this.questionId undefined on re-run) | Experience Community
Skip to main content
Question

Question JS breaks after language switch (this.questionId undefined on re-run)

  • August 12, 2026
  • 1 reply
  • 43 views

vgayraud
QPN Level 8 ●●●●●●●●
Forum|alt.badge.img+65
  • QPN Level 8 ●●●●●●●●

New Survey Taking Experience. Switching language mid-survey remounts the question DOM and re-runs addOnReady. On that re-run this is a bare internal object:

[ctx] ee  hasQid= undefined  hasGetChoices= undefined  keys= []
getInstance(QID17)= function

So this.questionId is undefined, selectors built from it return null, and this.getChoices() throws. First pass is fine, only the translate replay is broken. Stack: onTranslate → onEntered → notify → forEach over registered custom JS.

Also: the outgoing tree is still mounted during the replay (duplicate section.question ids), and the JS source seems re-evaluated per render, so caching on the callback itself doesn't survive.

QuestionData.getInstance(qid) still works during the failing pass, so the workaround is to capture the qid on the first pass, park it outside the callback, and use getInstance() instead of this.

Scripts that only write embedded data are unaffected. Ones binding listeners or enforcing answer logic fail silently. Page looks fine, logic is gone.

What seems to have changed: these scripts ran fine for a long time, and the addOnReady re-run on language switch is longstanding behaviour I've relied on elsewhere. So the re-run itself isn't new, What looks new is the receiver: on the replay, this is no longer the QuestionData. Also seeing the outgoing and incoming trees briefly both mounted (duplicate section.question ids), though I can't say whether that part is new.

 

Anyone else seeing this, and does it line up with a JFE release on your side?

1 reply

vgayraud
QPN Level 8 ●●●●●●●●
Forum|alt.badge.img+65
  • Author
  • QPN Level 8 ●●●●●●●●
  • August 13, 2026

Follow-up: instrumented it. Two corrections to my post above.

It's a different class, not an unbound QuestionData:

initial mount : constructor=te  own keys=["questionId"]  39 prototype members
after switch : constructor=ee own keys=[] 11 prototype members

The 11 survivors are all page-level (clickNextButton, hideNextButton, getQuestionDisplayed…). Not one question-scoped method. The translate path passes the page-level receiver where the question-level one belongs.

Correction 1: getInstance() is only half usable. getQuestionContainer() works, but getChoices() / getAnswers() throw MissingQuestionRef.

Correction 2: Qualtrics.SurveyEngine.QuestionInfo survives fully populated, better fallback. QuestionInfo[qid].ChoicesgetChoices(), .AnswersgetAnswers(). Structure only, no response state.

All four hooks, and it persists for the life of the page:

switch → addOnUnload=ee → addOnload=ee → addOnReady=ee
then Next → addOnPageSubmit=ee

Control run, no switch: addOnPageSubmit gets te with a populated qid. And in one run addOnReady was ee at T+0 with addOnPageSubmit still ee 1000 ms later on a deliberate click, page settled, so not a transition window. Scope is per-page; the next page binds correctly again.

Reproduces on builds main.bcbf5a8d.js and main.1e789300.js, /jfe/ and /jfe2/, sandbox on sjc1 and pdx1, and client licenses on yul1.

Workaround that holds: capture this.questionId on the first pass into a window slot, read structure from QuestionInfo[qid], rely on this for nothing. The question JS source is re-evaluated per render, so caching on the callback function object does not survive.