{"record":{"id":"34b148e1f9b2b66e","repo":"wekan/wekan","slug":"swimlane-not-found","errorCode":"swimlane-not-found","errorMessage":"Swimlane not found on this board.","messagePattern":"Swimlane not found on this board\\.","errorType":"error_code","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"server/methods/icsImport.js","lineNumber":24,"sourceCode":"import Swimlanes from '/models/swimlanes';\nimport { ReactiveCache } from '/imports/reactiveCache';\nimport { icsToCards } from '/server/lib/icsImport';\nimport { Authentication } from '/server/authentication';\nimport { sendJsonResult } from '/server/apiMiddleware';\nimport { allowIsBoardMemberWithWriteAccess } from '/server/lib/utils';\nimport { tripCanary } from '/server/lib/canary';\n\n// Shared import logic used by both the Meteor method and the REST endpoint.\n// Validates that the target list/swimlane belong to the board (no cross-board\n// writes), parses the .ics text into card shapes and inserts them.\nasync function importIcsCards(userId, boardId, listId, swimlaneId, icsText) {\n  const list = await Lists.findOneAsync(listId);\n  if (!list || list.boardId !== boardId) {\n    throw new Meteor.Error('list-not-found', 'List not found on this board.');\n  }\n  const swimlane = await Swimlanes.findOneAsync(swimlaneId);\n  if (!swimlane || swimlane.boardId !== boardId) {\n    throw new Meteor.Error('swimlane-not-found', 'Swimlane not found on this board.');\n  }\n  const cardShapes = icsToCards(icsText, { boardId, listId, swimlaneId });\n  const cardIds = [];\n  for (const shape of cardShapes) {\n    const doc = {\n      title: shape.title,\n      description: shape.description,\n      boardId,\n      listId,\n      swimlaneId,\n      userId,\n      sort: cardIds.length,\n    };\n    if (shape.startAt) doc.startAt = shape.startAt;\n    if (shape.dueAt) doc.dueAt = shape.dueAt;\n    // eslint-disable-next-line no-await-in-loop\n    const cardId = await Cards.insertAsync(doc);\n    cardIds.push(cardId);","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/wekan/wekan/blob/eb1433158b1804bcf3edaa5cb18f08ae2e04d6c2/server/methods/icsImport.js#L6-L42","documentation":"importIcsCards (server/methods/icsImport.js:24) throws Meteor.Error('swimlane-not-found', 'Swimlane not found on this board.') when swimlaneId does not resolve to a swimlane, or the swimlane's boardId differs from the target boardId. Like the list check, this prevents cross-board writes during ICS import and mirrors the list validation immediately above it.","triggerScenarios":"Calling importIcsToBoard / the ICS REST endpoint with a swimlaneId from another board, a deleted swimlane, a default swimlane id from a template board, or a truncated/mistyped id.","commonSituations":"Integrations hardcoding a default swimlane id from a different WeKan instance; swimlanes removed during board reorganization while clients still cache the id; confusion between list order id and swimlane id in API payloads.","solutions":["Verify Swimlanes.findOneAsync(swimlaneId)?.boardId === boardId before the call, resolving the id from the target board's swimlanes.","If the board uses a single swimlane, fetch its swimlane via Swimlanes.findOneAsync({boardId}) instead of a hardcoded id.","Confirm the id is not actually a list id or board id (payload field mix-ups are common).","Recreate the missing swimlane on the target board or re-export config with current ids, then retry."],"exampleFix":"// before\nawait call('importIcsToBoard', boardId, listId, hardcodedSwimlaneId, icsText);\n// after\nlet swimlane = await Swimlanes.findOneAsync(hardcodedSwimlaneId);\nif (!swimlane || swimlane.boardId !== boardId) {\n  swimlane = await Swimlanes.findOneAsync({ boardId });\n}\nawait call('importIcsToBoard', boardId, listId, swimlane._id, icsText);","handlingStrategy":"validation","validationCode":"const swimlane = await Swimlanes.findOneAsync(swimlaneId);\nif (!swimlane || swimlane.boardId !== boardId) {\n  throw new Error(`swimlaneId ${swimlaneId} does not belong to board ${boardId}`);\n}","typeGuard":"function swimlaneBelongsToBoard(swimlane, boardId) {\n  return !!swimlane && swimlane.boardId === boardId;\n}","tryCatchPattern":"try {\n  await call('importIcsToBoard', boardId, listId, swimlaneId, icsText);\n} catch (e) {\n  if (e instanceof Meteor.Error && e.error === 'swimlane-not-found') {\n    // resolve default swimlane of target board and retry\n  } else throw e;\n}","preventionTips":["Resolve swimlaneId from Swimlanes.find({boardId}), never hardcode ids","Check swimlane.boardId === boardId before calling","Watch for payload field mix-ups between listId and swimlaneId","Refresh swimlane ids after board reorganization"],"tags":["validation","ics-import","cross-board","rest-api"],"backgroundTag":"cross-board-resource-mismatch","analyzedSha":"eb1433158b1804bcf3edaa5cb18f08ae2e04d6c2","analyzedAt":"2026-09-01T21:05:02.951Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T01:17:15.007Z"}