{"record":{"id":"289deaeb15d74413","repo":"paperclipai/paperclip","slug":"teams-destination-contains-an-invalid-service-url","errorCode":null,"errorMessage":"Teams destination contains an invalid service URL","messagePattern":"Teams destination contains an invalid service URL","errorType":"validation","errorClass":"TeamsServiceUrlValidationError","httpStatus":null,"severity":"error","filePath":"server/src/services/chat-sdk-runtime.ts","lineNumber":955,"sourceCode":"\nfunction teamsConversationRouteStateKey(conversationId: string): string {\n  const baseConversationId = conversationId.replace(/;messageid=[^;]+/i, \"\");\n  return `teams:serviceUrl:conversation:${Buffer.from(baseConversationId).toString(\"base64url\")}`;\n}\n\nconst TEAMS_ACCEPTED_ACTIVITY_CACHE_TTL_MS = 30 * 24 * 60 * 60 * 1_000;\n\nfunction normalizedTeamsServiceUrl(value: unknown): string {\n  if (typeof value !== \"string\" || value.length > 2048) {\n    throw new TeamsServiceUrlValidationError(\n      \"Teams destination is missing its verified service URL\",\n    );\n  }\n  let parsed: URL;\n  try {\n    parsed = new URL(value);\n  } catch {\n    throw new TeamsServiceUrlValidationError(\n      \"Teams destination contains an invalid service URL\",\n    );\n  }\n  if (\n    parsed.protocol !== \"https:\" ||\n    parsed.username ||\n    parsed.password ||\n    parsed.search ||\n    parsed.hash\n  ) {\n    throw new TeamsServiceUrlValidationError(\n      \"Teams destination contains an invalid service URL\",\n    );\n  }\n  return parsed.toString().replace(/\\/+$/, \"\");\n}\n\nfunction trustedTeamsServiceUrl(","sourceCodeStart":937,"sourceCodeEnd":973,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/services/chat-sdk-runtime.ts#L937-L973","documentation":"normalizedTeamsServiceUrl parses the serviceUrl with the URL constructor; if parsing fails it throws TeamsServiceUrlValidationError with 'Teams destination contains an invalid service URL'. This rejects strings that are not syntactically valid absolute URLs.","triggerScenarios":"Calling the Teams destination normalization with a serviceUrl string such as 'not-a-url', 'localhost:3979/api/messages' without scheme prefix issues, or a garbled/truncated string that new URL(value) cannot parse.","commonSituations":"Hand-edited config where https:// was dropped; a truncated URL from a bad DB write; using a relative path or hostname-only value instead of an absolute URL.","solutions":["Provide a fully-qualified absolute URL including scheme, e.g. https://smba.trafficmanager.net/.../.","Fix the stored destination record so serviceUrl is the exact value from the Teams activity.","Trim whitespace/control characters that may make the URL unparseable.","Log and inspect the failing value to confirm whether the record was truncated or misconfigured."],"exampleFix":"// before\nserviceUrl: \"smba.trafficmanager.net/americas\"\n// after\nserviceUrl: \"https://smba.trafficmanager.net/americas\"","handlingStrategy":"validation","validationCode":"let parsed: URL;\ntry { parsed = new URL(dest.serviceUrl); } catch { throw new Error(\"serviceUrl is not an absolute URL\"); }","typeGuard":"function isAbsoluteUrl(value: string): boolean {\n  try { new URL(value); return true; } catch { return false; }\n}","tryCatchPattern":"try {\n  const url = normalizedTeamsServiceUrl(dest.serviceUrl);\n} catch (e) {\n  if (e instanceof TeamsServiceUrlValidationError) {\n    // log the raw value and require the exact serviceUrl from the Teams activity\n  }\n}","preventionTips":["Never hand-type serviceUrl values; copy them verbatim from the Bot Connector activity.","Validate with new URL() before persisting destination rows.","Trim whitespace/control characters from stored URLs.","Reject hostname-only strings lacking a scheme at ingestion."],"tags":["teams","url-validation","bot-framework"],"backgroundTag":"invalid-url-format","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}