{"record":{"id":"c5148d59e17fc404","repo":"jackwener/OpenCLI","slug":"mercury-reimbursement-form-fields-were-not-all-fil","errorCode":null,"errorMessage":"Mercury reimbursement form fields were not all filled: ${missing.join(', ')}","messagePattern":"Mercury reimbursement form fields were not all filled: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/mercury/reimbursement-draft.js","lineNumber":81,"sourceCode":"        if (!upload || upload.uploaded !== true || upload.files !== 1) {\n            throw new CommandExecutionError('Mercury receipt upload did not confirm exactly one uploaded file');\n        }\n        if (upload.target !== RECEIPT_INPUT_SELECTOR || upload.matches_n !== 1) {\n            throw new CommandExecutionError('Mercury receipt upload did not confirm the intended receipt input');\n        }\n        const uploadedNames = Array.isArray(upload.file_names) ? upload.file_names : [];\n        if (!uploadedNames.includes(receiptBasename(input.receipt))) {\n            throw new CommandExecutionError('Mercury receipt upload did not confirm the expected receipt file');\n        }\n\n        if (input.ocrWaitSeconds > 0) await page.wait({ time: input.ocrWaitSeconds });\n\n        const fields = await fillReimbursementFields(page, input);\n        await page.wait({ time: 1 });\n        const expectedFields = ['amount', 'currency', 'date', 'merchant', 'category', 'notes'];\n        const missing = expectedFields.filter((key) => !fields.touched[key]);\n        if (missing.length > 0) {\n            throw new CommandExecutionError(`Mercury reimbursement form fields were not all filled: ${missing.join(', ')}`);\n        }\n\n        const reviewClick = await page.evaluate(`(() => {\n            const norm = (s) => String(s || '').replace(/\\\\s+/g, ' ').trim().toLowerCase();\n            const candidates = Array.from(document.querySelectorAll('button, a, [role=\"button\"], [role=\"link\"]'))\n              .filter((node) => {\n                const style = window.getComputedStyle(node);\n                return style.visibility !== 'hidden' && style.display !== 'none' && node.offsetParent !== null;\n              });\n            const el = candidates.find((node) => norm(node.innerText || node.textContent || '') === 'review');\n            if (!el) return { clicked: false };\n            el.click();\n            return { clicked: true, text: el.innerText || el.textContent || '' };\n        })()`);\n        if (!reviewClick || typeof reviewClick !== 'object' || typeof reviewClick.clicked !== 'boolean') {\n            throw new CommandExecutionError('Mercury returned malformed Review click result');\n        }\n        if (!reviewClick.clicked) {","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/mercury/reimbursement-draft.js#L63-L99","documentation":"Thrown when `fillReimbursementFields` reports that one or more of the six required expense fields (amount, currency, date, merchant, category, notes) were not marked as touched — i.e. the command could not confirm it actually set every field in the Mercury reimbursement form. The message lists the missing field keys. This prevents advancing to Review with a partially filled draft.","triggerScenarios":"Running reimbursement-draft when a field's selector no longer matches after a Mercury UI change, OCR of the uploaded receipt overwrites fields after fill (race with input.ocrWaitSeconds too short), a field is disabled/hidden (e.g. currency locked to a default), or input coercion produces an empty value that the fill helper skips.","commonSituations":"ocr-wait-seconds too low so Mercury's OCR pass rewrites amount/merchant/notes after the CLI fills them; category string not matching any Mercury option so the select never updates; date format rejected by the custom date picker; field keys missing from fillReimbursementFields' touched tracking after a utils.js refactor.","solutions":["Increase --ocr-wait-seconds (default 8) so Mercury's OCR finishes before/after field filling doesn't overwrite values.","Inspect the listed missing field in the Mercury dialog DOM and update its selector/logic in fillReimbursementFields (clis/mercury/utils.js).","Verify the CLI argument values are non-empty and valid (date as YYYY-MM-DD, amount numeric, category matching a Mercury option).","Check fillReimbursementFields still records fields.touched[key] = true for every successfully filled field after any refactor."],"exampleFix":"// before\nopencli mercury reimbursement-draft --receipt r.png --amount 140.00 --date 2026-06-26 --merchant \"M\" --notes \"n\"\n// after (raise OCR wait and supply explicit currency/category)\nopencli mercury reimbursement-draft --receipt r.png --amount 140.00 --currency CNY --date 2026-06-26 --merchant \"M\" --category \"Marketing & Advertising\" --notes \"n\" --ocr-wait-seconds 15","handlingStrategy":"validation","validationCode":"const required = ['receipt','amount','currency','date','merchant','category','notes'];\nfor (const k of required) {\n  if (!kwargs[k] || String(kwargs[k]).trim() === '') {\n    throw new Error(`missing required arg: ${k}`);\n  }\n}\nif (!/^\\d{4}-\\d{2}-\\d{2}$/.test(kwargs.date)) {\n  throw new Error('date must be YYYY-MM-DD');\n}","typeGuard":"function allFieldsTouched(fields, keys = ['amount','currency','date','merchant','category','notes']) {\n  return keys.every((k) => fields?.touched?.[k] === true);\n}","tryCatchPattern":"try {\n  await opencli(['mercury', 'reimbursement-draft', ...args]);\n} catch (e) {\n  const m = String(e.message).match(/not all filled: (.+)/);\n  if (m) {\n    // retry with higher --ocr-wait-seconds for fields: m[1]\n  } else throw e;\n}","preventionTips":["Supply all field arguments explicitly rather than relying on defaults/OCR.","Raise --ocr-wait-seconds when receipts trigger Mercury's OCR rewrite.","Keep fillReimbursementFields selectors current with Mercury's markup.","Confirm category strings match Mercury's option labels exactly."],"tags":["form-fill","ocr-race","mercury","browser-automation"],"backgroundTag":"form-field-fill-incomplete","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}