Skip to content

Commit 696d24a

Browse files
authored
PLU-596: Elevated Telegram ETIMEDOUT during tcp.connect (#1272)
## Problem Elevated Telegram ETIMEDOUT during tcp.connect ## Solution Online threads suggest that the fix is to resolve using ipv4 instead of ipv6 https://community.n8n.io/t/solved-telegram-api-timeouts-ipv4-ipv6-dns-resolution-issue/170482 ## Tests - [ ] Can get telegram channels - [ ] Can send telegram messages
1 parent a0db6f1 commit 696d24a

File tree

6 files changed

+39
-2
lines changed

6 files changed

+39
-2
lines changed

packages/backend/src/apps/telegram-bot/actions/send-message/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { IRawAction } from '@plumber/types'
22

33
import StepError from '@/errors/step'
4+
import logger from '@/helpers/logger'
45

56
import { escapeMarkdown, sanitizeMarkdown } from '../../common/markdown-v1'
67
import { throwSendMessageError } from '../../common/throw-errors'
@@ -88,6 +89,10 @@ const action: IRawAction = {
8889
}
8990
try {
9091
const response = await $.http.post('/sendMessage', payload)
92+
// logging for debugging
93+
logger.info(
94+
`Telegram ip success: ${response.request?.socket?.remoteAddress}`,
95+
)
9196
$.setActionItem({
9297
raw: response.data,
9398
})
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { TBeforeRequest } from '@plumber/types'
2+
3+
import https from 'https'
4+
5+
// Singleton HTTPS agent configured for IPv4 only
6+
// This helps avoid DNS timeout issues with Telegram's API
7+
const httpsAgent = new https.Agent({
8+
family: 4, // Force IPv4 resolution
9+
keepAlive: true,
10+
timeout: 30000, // 30 second timeout
11+
})
12+
13+
const forceIpv4: TBeforeRequest = async ($, requestConfig) => {
14+
// Only apply to HTTPS requests (Telegram API uses HTTPS)
15+
if (requestConfig.baseURL?.startsWith('https://')) {
16+
requestConfig.httpsAgent = httpsAgent
17+
}
18+
19+
return requestConfig
20+
}
21+
22+
export default forceIpv4

packages/backend/src/apps/telegram-bot/common/throw-errors.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export async function throwSendMessageError(
2626
err.message.includes('ETIMEDOUT') ||
2727
err.code === 'ETIMEDOUT'
2828
) {
29+
logger.error(`Telegram ip error: ${err.resolvedIp}`)
2930
throw new RetriableError({
3031
error: 'Timeout error. Telegram may be experiencing issues.',
3132
delayInMs: 'default',

packages/backend/src/apps/telegram-bot/dynamic-data/get-chat-ids.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import {
44
IGlobalVariable,
55
} from '@plumber/types'
66

7+
import logger from '@/helpers/logger'
8+
79
import {
810
HasTelegramChat,
911
TelegramGetUpdatesResponse,
@@ -49,9 +51,11 @@ const dynamicData: IDynamicData = {
4951
const chatIdsMap: { name: string; value: string }[] = []
5052
const chatIdsSet = new Set<number>()
5153
try {
52-
const { data } = await $.http.get<TelegramGetUpdatesResponse>(
54+
const { data, request } = await $.http.get<TelegramGetUpdatesResponse>(
5355
getUpdatesApi,
5456
)
57+
// logging for debugging
58+
logger.info(`Telegram ip success: ${request?.socket?.remoteAddress}`)
5559

5660
if (!data.result) {
5761
return {

packages/backend/src/apps/telegram-bot/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { IApp } from '@plumber/types'
33
import { getGenericAppQueue } from '@/queues/helpers/get-generic-app-queue'
44

55
import addAuthHeader from './common/add-auth-header'
6+
import forceIpv4 from './common/force-ipv4'
67
import rateLimitHandler from './common/interceptor/rate-limit'
78
import actions from './actions'
89
import auth from './auth'
@@ -17,7 +18,7 @@ const app: IApp = {
1718
baseUrl: 'https://telegram.org',
1819
apiBaseUrl: 'https://api.telegram.org',
1920
primaryColor: '2AABEE',
20-
beforeRequest: [addAuthHeader],
21+
beforeRequest: [forceIpv4, addAuthHeader],
2122
requestErrorHandler: rateLimitHandler,
2223
dynamicData,
2324
auth,

packages/backend/src/errors/http.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import BaseError from './base'
77
export default class HttpError extends BaseError {
88
response: AxiosResponse
99
code?: string
10+
resolvedIp?: string
1011

1112
constructor(error: AxiosError) {
1213
const computedError =
@@ -26,6 +27,9 @@ export default class HttpError extends BaseError {
2627
// Pass code along
2728
this.code = error.code
2829

30+
// add resolved ip for debugging
31+
this.resolvedIp = error.request?.socket?.remoteAddress
32+
2933
//
3034
// Only preserve selected headers to avoid storing sensitive data.
3135
//

0 commit comments

Comments
 (0)