{"record":{"id":"828c38e5bce7b626","repo":"different-ai/openwork","slug":"attachment-hostname-hostname-did-not-resolve","errorCode":null,"errorMessage":"Attachment hostname ${hostname} did not resolve.","messagePattern":"Attachment hostname (.+?) did not resolve\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/server/src/extensions/google-workspace.ts","lineNumber":841,"sourceCode":"// it the way the managed MCP undici dispatcher does.\nasync function assertGmailAttachmentHostPublic(url: URL): Promise<void> {\n  const hostname = url.hostname.replace(/^\\[|\\]$/g, \"\");\n  if (isIP(hostname) !== 0) return;\n  let addresses: LookupAddress[];\n  try {\n    addresses = await lookup(hostname, { all: true, verbatim: true });\n  } catch {\n    throw new ApiError(502, \"attachment_fetch_failed\", \"Attachment url hostname could not be resolved\", { hostname });\n  }\n  if (!addresses.length || addresses.some((entry) => isLocalManagedMcpPrivateAddress(entry.address))) {\n    throw new ApiError(400, \"invalid_payload\", \"Attachment url must resolve to a public address\", { hostname });\n  }\n}\n\nconst resolveGmailAttachmentAddresses: GmailAttachmentAddressResolver = (hostname, options) => lookup(hostname, options);\n\nfunction validateGmailAttachmentAddresses(hostname: string, addresses: LookupAddress[]): void {\n  if (!addresses.length) throw new Error(`Attachment hostname ${hostname} did not resolve.`);\n  const privateAddress = addresses.find((entry) => isLocalManagedMcpPrivateAddress(entry.address));\n  if (privateAddress) {\n    throw new Error(`Attachment hostname ${hostname} resolved to a private or reserved address (${privateAddress.address}).`);\n  }\n}\n\n/**\n * Resolves and validates the attachment host inside the socket connector. The\n * same answers are handed to net.connect, closing the DNS-rebinding window\n * between a preflight lookup and the actual connection.\n */\nexport function createGmailAttachmentPublicLookup(\n  resolver: GmailAttachmentAddressResolver = resolveGmailAttachmentAddresses,\n): LookupFunction {\n  return (hostname, options, callback) => {\n    const lookupOptions: LookupAllOptions = { ...options, all: true, verbatim: true };\n    void resolver(hostname, lookupOptions).then((addresses) => {\n      try {","sourceCodeStart":823,"sourceCodeEnd":859,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/apps/server/src/extensions/google-workspace.ts#L823-L859","documentation":"validateGmailAttachmentAddresses re-checks the addresses actually used for the socket connection (handed to net.connect to close the DNS-rebinding window). A plain Error (not ApiError) is thrown when the resolver returned an empty list — the hostname did not resolve to any address at connect time. It is plain Error because it is evaluated inside the socket connector against pre-resolved answers.","triggerScenarios":"The GmailAttachmentAddressResolver callback yields [] for the hostname — i.e. zero DNS answers at connection setup, typically when the earlier lookup raced with a DNS change or the resolver was mocked/failed silently.","commonSituations":"DNS record removed between validation and connect (TOCTOU on DNS); custom resolver injected for tests returning empty results; network flakiness dropping all answers; very short TTL records expiring mid-flow.","solutions":["Retry the attachment download; transient DNS gaps usually resolve on a second attempt.","Verify the hostname still has DNS records (dig) and fix or update the URL.","Check any injected resolveGmailAttachmentAddresses override in tests — it must return at least one address.","Increase resolver reliability (use a stable upstream resolver) if this recurs in production."],"exampleFix":"// before (test override)\nconst resolver = async () => [];\n// after\nconst resolver = async (h, o) => lookup(h, o); // return real addresses","handlingStrategy":"retry","validationCode":"import { lookup } from \"node:dns/promises\";\nasync function hasDnsAnswers(hostname: string): Promise<boolean> {\n  try { return (await lookup(hostname, { all: true, verbatim: true })).length > 0; } catch { return false; }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await fetchGmailAttachment({ url });\n} catch (e) {\n  if (e instanceof Error && /did not resolve\\./.test(e.message)) {\n    await sleep(1500);\n    return fetchGmailAttachment({ url }); // DNS may have recovered between attempts\n  }\n  throw e;\n}","preventionTips":["In tests, never inject an address resolver that returns an empty array.","Retry on transient DNS failures with small backoff.","Monitor DNS record TTLs for attachment hosts.","Confirm hostname still exists if the error repeats."],"tags":["dns","network","gmail","attachments"],"backgroundTag":"dns-resolution-failed","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}