{"record":{"id":"59b7cbee5fd7912b","repo":"multica-ai/multica","slug":"file-exceeds-100-mb-limit","errorCode":null,"errorMessage":"File exceeds 100 MB limit","messagePattern":"File exceeds 100 MB limit","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/hooks/use-file-upload.ts","lineNumber":119,"sourceCode":"  // In-flight counter, NOT a single boolean. Callers fire multiple uploads\n  // concurrently (drag-drop of N files, paste with multiple images) and the\n  // boolean shape would flip false as soon as the FIRST upload's finally ran\n  // — even though N-1 are still mid-request. Surfaces consuming `uploading`\n  // (the quick-create submit gate, the editor's \"Uploading…\" button label)\n  // would then unblock submit while uploads are still in flight, causing\n  // `stripBlobUrls` to erase the still-pending images from the markdown and\n  // their attachment ids never to be bound (MUL-3339).\n  //\n  // The exposed `uploading: boolean` keeps the existing call-site contract\n  // (`{ uploading } = useFileUpload(api)` everywhere); only the internal\n  // tracking shape changes.\n  const [inFlight, setInFlight] = useState(0);\n  const uploading = inFlight > 0;\n\n  const upload = useCallback(\n    async (file: File, ctx?: UploadContext): Promise<UploadResult | null> => {\n      if (file.size > MAX_FILE_SIZE) {\n        throw new Error(\"File exceeds 100 MB limit\");\n      }\n\n      setInFlight((n) => n + 1);\n      try {\n        const att: Attachment = await api.uploadFile(file, {\n          issueId: ctx?.issueId,\n          commentId: ctx?.commentId,\n          chatSessionId: ctx?.chatSessionId,\n        });\n        return toUploadResult(att);\n      } finally {\n        setInFlight((n) => n - 1);\n      }\n    },\n    [api],\n  );\n\n  const uploadWithToast = useCallback(","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/packages/core/hooks/use-file-upload.ts#L101-L137","documentation":"Wrap thrown by prepareHermesHome when detachHermesMemories fails. When NO memory store is configured (no agent to key on, or an unresolvable profile dir), the overlay must fall back to a fresh task-local memories/ dir — detach removes/neutralizes any inherited memories link so state does not leak between tasks. Failure to do that is fatal because it would break memory isolation.","triggerScenarios":"prepareHermesHome is called with an empty memoryStore and detachHermesMemories(hermesHome) errors — e.g. it cannot remove or replace an existing memories/ link/dir inside hermes-home due to permissions, an undeletable entry, or a full disk.","commonSituations":"Recycled env-root whose hermes-home still carries a memories/ link owned by another user; read-only overlay; daemon UID change.","solutions":["Inspect <envRoot>/hermes-home/memories and remove/repair the stale entry manually so detach can proceed.","Fix ownership of the hermes-home tree for the daemon user.","Delete the whole per-task env-root to force a clean rebuild.","If a memory store is actually intended for this agent, configure it so the mount path is taken instead of the detach fallback."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// when no store is configured, ensure a clean slate for the fallback\nif memoryStore == \"\" {\n    if err := os.RemoveAll(filepath.Join(envRoot, \"hermes-home\", \"memories\")); err != nil {\n        return err\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := prepareHermesHome(...); err != nil {\n    if strings.Contains(err.Error(), \"create task memories dir\") {\n        // remove the conflicting memories/ entry or wipe env-root, retry prepare\n    }\n}","preventionTips":["Wipe recycled env-roots before reuse.","Fix hermes-home ownership after daemon UID changes.","Configure a memory store when persistence is intended — do not rely on the fallback."],"tags":["go","hermes","execenv","memory","filesystem","isolation"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}