{"record":{"id":"129755f3406c5548","repo":"tailwindlabs/headlessui","slug":"missing-focus-first-focus-previous-focus-next-or-129755","errorCode":null,"errorMessage":"Missing Focus.First, Focus.Previous, Focus.Next or Focus.Last","messagePattern":"Missing Focus\\.First, Focus\\.Previous, Focus\\.Next or Focus\\.Last","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@headlessui-vue/src/utils/focus-management.ts","lineNumber":222,"sourceCode":"      : container?.ownerDocument) ?? document\n\n  let elements = Array.isArray(container)\n    ? sorted\n      ? sortByDomNode(container)\n      : container\n    : getFocusableElements(container)\n\n  if (skipElements.length > 0 && elements.length > 1) {\n    elements = elements.filter((x) => !skipElements.includes(x))\n  }\n\n  relativeTo = relativeTo ?? (ownerDocument.activeElement as HTMLElement)\n\n  let direction = (() => {\n    if (focus & (Focus.First | Focus.Next)) return Direction.Next\n    if (focus & (Focus.Previous | Focus.Last)) return Direction.Previous\n\n    throw new Error('Missing Focus.First, Focus.Previous, Focus.Next or Focus.Last')\n  })()\n\n  let startIndex = (() => {\n    if (focus & Focus.First) return 0\n    if (focus & Focus.Previous) return Math.max(0, elements.indexOf(relativeTo)) - 1\n    if (focus & Focus.Next) return Math.max(0, elements.indexOf(relativeTo)) + 1\n    if (focus & Focus.Last) return elements.length - 1\n\n    throw new Error('Missing Focus.First, Focus.Previous, Focus.Next or Focus.Last')\n  })()\n\n  let focusOptions = focus & Focus.NoScroll ? { preventScroll: true } : {}\n\n  let offset = 0\n  let total = elements.length\n  let next = undefined\n  do {\n    // Guard against infinite loops","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/tailwindlabs/headlessui/blob/eea57cf46fd6767ed1059012f7073b88eb159fba/packages/@headlessui-vue/src/utils/focus-management.ts#L204-L240","documentation":"`focusIn(container, focus)` from Headless UI's focus-management utility computes a traversal direction from the `focus` bitmask. It requires one of the directional flags Focus.First, Focus.Previous, Focus.Next, or Focus.Last; if none is set, the direction computation throws immediately.","triggerScenarios":"Calling `focusIn(el, Focus.NoScroll)` or `focusIn(el, 0)` (only modifier flags set); passing a custom numeric value that doesn't include a direction bit; building the flags dynamically and accidentally passing only Focus.WrapAround/NoScroll.","commonSituations":"Custom keyboard handlers in menus/dialogs that pass only modifier flags; refactor typos where the direction constant is dropped; calling the internal `focusIn`/`focusFrom` API directly instead of higher-level components.","solutions":["Include exactly one direction flag: `focusIn(container, Focus.First | Focus.NoScroll)`.","If computing flags dynamically, assert a direction bit is present before calling: `(flags & (Focus.First|Focus.Previous|Focus.Next|Focus.Last)) !== 0`.","Prefer using the library's built-in components/keyboard handling rather than calling focusIn directly."],"exampleFix":"// before\nfocusIn(container, Focus.NoScroll)\n\n// after\nfocusIn(container, Focus.First | Focus.NoScroll)","handlingStrategy":"validation","validationCode":"const DIRECTION = Focus.First | Focus.Previous | Focus.Next | Focus.Last\nif ((flags & DIRECTION) === 0) flags |= Focus.First\nfocusIn(container, flags)","typeGuard":"const hasDirection = (f: number) => (f & (Focus.First | Focus.Previous | Focus.Next | Focus.Last)) !== 0","tryCatchPattern":null,"preventionTips":["Always OR a direction flag with modifiers.","Import Focus from the package itself to avoid undefined flags.","Prefer built-in components' keyboard handling over direct focusIn calls."],"tags":["headlessui","focus","bitmask","argument-validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"eea57cf46fd6767ed1059012f7073b88eb159fba","analyzedAt":"2026-08-28T19:22:46.163Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}