# gRPC: панель генерирует несуществующее поле mode вместо multiMode

**URL:** https://f.docs.rw/t/topic/784
**Category:** Баг-репорты
**Created:** 2026-09-27T20:27:33Z
**Posts:** 3

## Post 1 by @magnus_gp — 2026-09-27T20:27:33Z

При генерации клиентского конфига настройка `multiMode` для gRPC-транспорта выписывается под именем **`mode`**. У gRPC в Xray поля `mode` не существует — Go молча отбрасывает неизвестные ключи JSON, поэтому `multiMode` у клиента всегда остаётся `false`, что бы администратор ни выставил в панели. Мультиплексирование gRPC не работает никогда.

`backend-main/src/modules/subscription-template/generators/xray-json.generator.service.ts:115-119`

```
grpc: (host) => ({
    serviceName: host.transportOptions.serviceName,
    authority: host.transportOptions.authority,
    mode: !!host.transportOptions.multiMode, // ← должно быть multiMode
}),
```

В схеме панели поле названо верно (`backend-main/libs/contract/models/resolved-proxy-config.schema.ts:73-77`):

```
export const GrpcTransportOptionsSchema = z.object({
    authority: z.string().nullable(),
    serviceName: z.string().nullable(),
    multiMode: z.boolean(),
});
```

То есть ошибка только на этапе генерации конфига.

Для справки — структура gRPC-транспорта в Xray, `infra/conf/transport_method.go:578-587`:

```
type GRPCConfig struct {
    Authority string `json:"authority"`
    ServiceName string `json:"serviceName"`
    MultiMode bool `json:"multiMode"`
    IdleTimeout int32 `json:"idle_timeout"`
    HealthCheckTimeout int32 `json:"health_check_timeout"`
    PermitWithoutStream bool `json:"permit_without_stream"`
    InitialWindowsSize int32 `json:"initial_windows_size"`
    UserAgent string `json:"user_agent"`
}
```

Поле `mode` в Xray есть только у XHTTP (там же, строка 260).

Баг незаметен, потому что подключение устанавливается: сервер регистрирует оба метода — и `Tun`, и `TunMulti` (`transport/internet/grpc/hub.go:132`). Клиент просто уходит в немультиплексированный режим, и со стороны всё выглядит работающим.

## Исправление

```
grpc: (host) => ({
    serviceName: host.transportOptions.serviceName,
    authority: host.transportOptions.authority,
    multiMode: !!host.transportOptions.multiMode,
}),
```

## Сопутствующая проблема: недоступные параметры keepalive

Схема и генератор поддерживают для gRPC только три поля. Параметры `idle_timeout`, `health_check_timeout` и `permit_without_stream` выставить через панель невозможно — их нет ни в схеме, ни в генераторе.

Для мобильных клиентов это ощутимо. Без `permit_without_stream: true` gRPC не отправляет PING, когда нет активных потоков, а приложение в фоне находится именно в этом состоянии. Соединение умирает незаметно: клиент показывает «подключено», трафик не идёт до переподключения вручную.

Предложение — добавить их по аналогии с остальными полями:

```
// resolved-proxy-config.schema.ts
export const GrpcTransportOptionsSchema = z.object({
    authority: z.string().nullable(),
    serviceName: z.string().nullable(),
    multiMode: z.boolean(),
    idleTimeout: z.int().nullable(),
    healthCheckTimeout: z.int().nullable(),
    permitWithoutStream: z.boolean().nullable(),
});
```

```
// xray-json.generator.service.ts
grpc: (host) => ({
    serviceName: host.transportOptions.serviceName,
    authority: host.transportOptions.authority,
    multiMode: !!host.transportOptions.multiMode,
    ...(host.transportOptions.idleTimeout != null && {
        idle_timeout: host.transportOptions.idleTimeout,
    }),
    ...(host.transportOptions.healthCheckTimeout != null && {
        health_check_timeout: host.transportOptions.healthCheckTimeout,
    }),
    ...(host.transportOptions.permitWithoutStream != null && {
        permit_without_stream: host.transportOptions.permitWithoutStream,
    }),
}),
```

Имена внутри панели могут быть любыми, но в сгенерированный конфиг они обязаны попадать ровно в том виде, в котором их ждёт Xray — со подчёркиваниями: `idle_timeout`, `health_check_timeout`, `permit_without_stream`. Расхождение здесь даёт ту же тихую поломку, что и с `mode`.

---

## Post 2 by @remnawave — 2026-09-27T21:15:39Z

Исправление названия – будет.

Касательно новых полей – никаких новых полей у “хоста” не планируется. Существует объект `Mapper` – используйте его.

---

## Post 3 by @remnawave — 2026-10-06T01:13:14Z

Исправление доступно в версии панели 3.4.5.

---

## Post 4 by @system — 2026-10-08T01:13:49Z

Эта тема была автоматически закрыта через 2 дня после последнего ответа. В ней больше нельзя отвечать.
