{"record":{"id":"f3844393d810eb41","repo":"jackwener/OpenCLI","slug":"instagram-reel-caption-did-not-stick-before-sharin","errorCode":null,"errorMessage":"Instagram reel caption did not stick before sharing","messagePattern":"Instagram reel caption did not stick before sharing","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/instagram/reel.js","lineNumber":574,"sourceCode":"          clipboardData: dt,\n          bubbles: true,\n          cancelable: true,\n        }));\n        editor.blur();\n        return { ok: true, mode: 'contenteditable' };\n      }\n      return { ok: false };\n    })(${JSON.stringify(content)})\n  `);\n}\nasync function ensureCaptionFilled(page, content) {\n    for (let attempt = 0; attempt < 6; attempt += 1) {\n        if (await captionMatches(page, content))\n            return;\n        if (attempt < 5)\n            await page.wait({ time: 0.5 });\n    }\n    throw new CommandExecutionError('Instagram reel caption did not stick before sharing');\n}\nfunction buildReelPublishStatusProbeJs() {\n    return `\n    (() => {\n      const isVisible = (el) => {\n        if (!(el instanceof HTMLElement)) return false;\n        const style = window.getComputedStyle(el);\n        const rect = el.getBoundingClientRect();\n        return style.display !== 'none'\n          && style.visibility !== 'hidden'\n          && rect.width > 0\n          && rect.height > 0;\n      };\n      const dialogs = Array.from(document.querySelectorAll('[role=\"dialog\"]')).filter((el) => isVisible(el));\n      const dialogText = dialogs.map((el) => (el.textContent || '').replace(/\\\\s+/g, ' ').trim()).join(' ');\n      const lower = dialogText.toLowerCase();\n      const url = window.location.href;\n      const sharingVisible = /sharing/.test(lower);","sourceCodeStart":556,"sourceCodeEnd":592,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/instagram/reel.js#L556-L592","documentation":"After inserting the caption text, ensureCaptionFilled polls captionMatches up to 6 times (0.5s apart, ~3s total) comparing the editor content (whitespace/nbsp-normalized) with the intended caption. If the editor content never equals the requested caption before the Share step, the library aborts with this error to avoid publishing a reel with a missing or truncated caption.","triggerScenarios":"captionMatches() returns false for all 6 attempts after page.insertText(content): the text never landed in the editor, was cleared by Instagram, or normalization (e.g. emoji, mention autocomplete, nbsp handling) makes the DOM text differ from the input.","commonSituations":"Captions containing @mentions or #hashtags where Instagram transforms the text into mention/entity nodes that don't serialize back to the raw string, captions with unusual unicode that insertText mangles, an Instagram UI update changing the Lexical editor structure so captionMatches reads the wrong node, or a re-render of the dialog wiping the inserted text.","solutions":["Simplify the caption: remove @mentions/#hashtags/emoji and retry to see if entity transformation is the cause.","Retry the run; a dialog re-render mid-insert can wipe the text and a second attempt often sticks.","Check the caption for characters that get normalized differently (non-breaking spaces, RTL marks, zero-width chars) and strip them.","Update the library if Instagram changed the editor DOM, so captionMatches reads the correct Lexical/text content."],"exampleFix":"// before\nconst caption = \"New reel! @instagram check it out \\u00a0\\u2028 thanks\";\nawait run({ caption });\n// after\nconst caption = \"New reel! check it out thanks\"; // plain text, no entities or exotic whitespace\nawait run({ caption });","handlingStrategy":"validation","validationCode":"// pre-normalize the caption the same way the library does before submitting\nconst normalized = (s) => s.replace(/\\u00a0/g, ' ').replace(/\\s+/g, ' ').trim();\nif (normalized(caption) !== caption.trim()) {\n  caption = normalized(caption); // avoid nbsp/whitespace mismatch on verification\n}","typeGuard":"null","tryCatchPattern":"try {\n  await client.shareReel({ videoPath, caption });\n} catch (err) {\n  if (String(err.message).includes('caption did not stick')) {\n    console.error('Caption not applied; reel not shared, safe to retry with plain-text caption');\n  } else throw err;\n}","preventionTips":["Use plain-text captions without @mention/#hashtag entities or exotic unicode","Strip non-breaking spaces and zero-width characters before submitting","Keep captions reasonably short to reduce editor transformation surprises","Pin/update the library version together with observed Instagram UI changes"],"tags":["instagram","automation","content-mismatch","browser-automation"],"backgroundTag":"caption-content-mismatch","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}