{"record":{"id":"1a42d0bc65d92ca2","repo":"paperclipai/paperclip","slug":"https-exposure-failed-tailscale-magicdns-hostname","errorCode":null,"errorMessage":"HTTPS exposure failed: Tailscale MagicDNS hostname unavailable","messagePattern":"HTTPS exposure failed: Tailscale MagicDNS hostname unavailable","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/src/services/workspace-runtime.ts","lineNumber":5622,"sourceCode":"    try {\n      exposureHostname = await workspaceRuntimeExposureDeps.resolveHostname();\n      reservedExposure.status.hostname = exposureHostname;\n      reservedExposure.status.updatedAt = new Date().toISOString();\n    } catch {\n      await workspaceRuntimeExposureDeps.broker\n        .remove(runtimeId, reservedExposure.handle)\n        .catch(() => undefined);\n      // The reservation deliberately keeps the winning pair's in-process claim for\n      // the caller to release on stop/teardown. No runtime record exists yet, so\n      // that teardown path can never run for this pair — releasing the broker\n      // reservation alone would leave the claim held. A hostname outage would then\n      // burn one pair per attempt, and a retry storm inside the claim TTL would\n      // report the range exhausted rather than the real cause.\n      exposurePortPairClaims.release({\n        appPort: reservedExposure.appPort,\n        hmrPort: reservedExposure.hmrPort,\n      });\n      throw new Error(\"HTTPS exposure failed: Tailscale MagicDNS hostname unavailable\");\n    }\n  }\n  const templateData = buildTemplateData({\n    workspace: input.workspace,\n    agent: input.agent,\n    issue: input.issue,\n    adapterEnv: input.adapterEnv,\n    port,\n  });\n  const serviceCwd =\n    port === identityPort\n      ? identity.serviceCwd\n      : resolveConfiguredPath(renderTemplate(asString(input.service.cwd, \".\"), templateData), input.workspace.cwd);\n  const env: Record<string, string> = {\n    ...sanitizeRuntimeServiceBaseEnv(process.env),\n    ...input.adapterEnv,\n  } as Record<string, string>;\n  for (const [key, value] of Object.entries(renderRuntimeServiceEnv({ envConfig, templateData }))) {","sourceCodeStart":5604,"sourceCodeEnd":5640,"githubUrl":"https://github.com/paperclipai/paperclip/blob/a7e689b3c35347b529cb9f54c9b9a8575a3dcab6/server/src/services/workspace-runtime.ts#L5604-L5640","documentation":"HTTPS exposure setup reserved ports and then tried to resolve a Tailscale MagicDNS hostname, which failed. Without a hostname the exposure cannot build a public HTTPS URL, so the reservation is torn down and the exposure attempt fails.","triggerScenarios":"Thrown at server/src/services/workspace-runtime.ts:5332 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Enable Tailscale MagicDNS on the tailnet and ensure this machine has a MagicDNS hostname, then retry the exposure.","Use a non-Tailscale exposure method if MagicDNS cannot be enabled."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"a7e689b3c35347b529cb9f54c9b9a8575a3dcab6","analyzedAt":"2026-08-18T22:49:45.177Z","contentChangedAt":"2026-08-18T22:49:45.177Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}