{"record":{"id":"2d3ac51ade5bd0f5","repo":"remix-run/react-router","slug":"cannot-submit-a-button-or-input-type-submit","errorCode":null,"errorMessage":"Cannot submit a <button> or <input type=\"submit\"> without a <form>","messagePattern":"Cannot submit a <button> or <input type=\"submit\"> without a <form>","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/react-router/lib/dom/dom.ts","lineNumber":300,"sourceCode":"  if (isFormElement(target)) {\n    // When grabbing the action from the element, it will have had the basename\n    // prefixed to ensure non-JS scenarios work, so strip it since we'll\n    // re-prefix in the router\n    let attr = target.getAttribute(\"action\");\n    action = attr ? stripBasename(attr, basename) : null;\n    method = target.getAttribute(\"method\") || defaultMethod;\n    encType = getFormEncType(target.getAttribute(\"enctype\")) || defaultEncType;\n\n    formData = new FormData(target);\n  } else if (\n    isButtonElement(target) ||\n    (isInputElement(target) &&\n      (target.type === \"submit\" || target.type === \"image\"))\n  ) {\n    let form = target.form;\n\n    if (form == null) {\n      throw new Error(\n        `Cannot submit a <button> or <input type=\"submit\"> without a <form>`,\n      );\n    }\n\n    // <button>/<input type=\"submit\"> may override attributes of <form>\n\n    // When grabbing the action from the element, it will have had the basename\n    // prefixed to ensure non-JS scenarios work, so strip it since we'll\n    // re-prefix in the router\n    let attr = target.getAttribute(\"formaction\") || form.getAttribute(\"action\");\n    action = attr ? stripBasename(attr, basename) : null;\n\n    method =\n      target.getAttribute(\"formmethod\") ||\n      form.getAttribute(\"method\") ||\n      defaultMethod;\n    encType =\n      getFormEncType(target.getAttribute(\"formenctype\")) ||","sourceCodeStart":282,"sourceCodeEnd":318,"githubUrl":"https://github.com/remix-run/react-router/blob/1fd704a7dabcbe3ae09d7387b460e6acaba30ec1/packages/react-router/lib/dom/dom.ts#L282-L318","documentation":"`getFormSubmissionInfo` was given a `<button>` or `<input type=submit|image>` whose `.form` property is `null`. There is no associated form, so there is nothing to read the action/method/formData from and submission cannot proceed.","triggerScenarios":"Calling `submit(submitter)` (or `<Form>`'s implicit submission) on a submit button that has no enclosing `<form>` and no `form` attribute pointing at one; programmatically submitting a detached button node; a button whose `<form>` was removed from the DOM before the click handler ran.","commonSituations":"A `<button type=\"submit\">` rendered outside any `<form>` (often a styling/layout accident); SSR markup that wraps the button in a form on the server but loses it on the client after hydration; React keying that re-parents the button away from its form.","solutions":["Ensure the submit button is a descendant of a `<form>` (or `<Form>`), or set `form=\"<formId>\"` pointing at a form in the same document.","If using `requestSubmit()`/`submit()` programmatically, pass the `<form>` element itself rather than the button.","Verify the form is actually mounted (not unmounted by an early state change) at submit time."],"exampleFix":"// before\nreturn (\n  <button type=\"submit\">Save</button>\n);\n\n// after\nreturn (\n  <Form method=\"post\">\n    <button type=\"submit\">Save</button>\n  </Form>\n);","handlingStrategy":"type-guard","validationCode":"function hasForm(submitter: HTMLElement | null): submitter is HTMLButtonElement | HTMLInputElement {\n  if (!submitter) return false;\n  if (submitter instanceof HTMLFormElement) return true;\n  return Boolean((submitter as HTMLButtonElement | HTMLInputElement).form);\n}\nif (!hasForm(submitter)) throw new Error('Submitter has no associated <form>');","typeGuard":"function isSubmitterWithForm(n: unknown): n is HTMLButtonElement | HTMLInputElement {\n  return n instanceof HTMLButtonElement || (n instanceof HTMLInputElement && (n.type === 'submit' || n.type === 'image')) && n.form != null;\n}","tryCatchPattern":null,"preventionTips":["Always render submit buttons inside a `<form>`/`<Form>`.","For split layouts, use the `form=\"id\"` attribute to associate a button with a form.","In React effects, confirm `form` is still mounted before calling submit."],"tags":["forms","dom","submission"],"backgroundTag":null,"analyzedSha":"1fd704a7dabcbe3ae09d7387b460e6acaba30ec1","analyzedAt":"2026-08-12T13:54:57.804Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}