v2rayA/v2rayA · error
bad request: unsupported touch type
Error message
bad request: unsupported touch type
What it means
Import() validates the TYPE of the target (server/subscription) before modifying it. If which.TYPE is neither configure.ServerType nor configure.SubscriptionServerType, modification is refused with this bad-request error. It is an input-validation guard against modifying entities the import API does not support.
Source
Thrown at service/server/service/import.go:70
urlLower := strings.ToLower(url)
if PluginManagerValidateLink(url) || common.HasAnyPrefix(urlLower, supportedPrefix) {
log.Trace("Import: url matches supported prefixes or is valid for PluginManager")
var obj serverObj.ServerObj
obj, err = ResolveURL(url)
if err != nil {
log.Warn("ResolveURL failed: %v", err)
return
}
if which != nil && which.ID > 0 {
// the request is to modify a server
ind := which.ID - 1
log.Info("Import: modifying server. ind=%v, which.ID=%v, which.TYPE=%v", ind, which.ID, which.TYPE)
if which.TYPE != configure.ServerType {
// Also support modifying subscription servers if the frontend allows it
// but for now, we primarily care about ServerType
if which.TYPE != configure.SubscriptionServerType {
log.Warn("Import: unsupported touch type for modification: %v", which.TYPE)
return fmt.Errorf("bad request: unsupported touch type")
}
}
if which.TYPE == configure.ServerType && (ind < 0 || ind >= configure.GetLenServers()) {
log.Warn("Import: invalid server index: %v", ind)
return fmt.Errorf("bad request: invalid index")
}
if err = configure.SetServer(ind, &configure.ServerRaw{ServerObj: obj}); err != nil {
log.Warn("Import: SetServer failed: %v", err)
return
}
log.Info("Import: SetServer success for index %v", ind)
css := configure.GetConnectedServers()
if css.Len() > 0 {
for _, cs := range css.Get() {
if which.TYPE == cs.TYPE && which.ID == cs.ID {
log.Info("Import: updating connected v2ray config")View on GitHub (pinned to 71e5442fc5)
Solutions
- Set which.TYPE to configure.ServerType (or SubscriptionServerType) before calling Import
- If importing into an existing server, fetch the target via configure and copy its TYPE rather than constructing one manually
- Fix the frontend/API client to send the correct touch type field
Example fix
// before
which := configure.Which{ID: 1, TYPE: configure.SubscriptionType}
err := service.Import(which, 0, obj)
// after
which := configure.Which{ID: 1, TYPE: configure.ServerType}
err := service.Import(which, 0, obj) Defensive patterns
Strategy: validation
Validate before calling
func validTouchType(t configure.TouchType) bool {
return t == configure.ServerType || t == configure.SubscriptionServerType
}
if !validTouchType(which.TYPE) {
return fmt.Errorf("refusing to import: unsupported touch type %v", which.TYPE)
} Type guard
func isServerOrSubServer(w configure.Which) bool {
return w.TYPE == configure.ServerType || w.TYPE == configure.SubscriptionServerType
} Prevention
- Always set TYPE explicitly when constructing Which structs
- Copy TYPE from an existing configured entity when modifying it
- Re-check client payloads after adding new TouchType values
When it happens
Trigger: Calling Import (via initConfigure or the PostImport API) with a Which struct whose TYPE field is an unsupported value, e.g. SubscriptionType or a zero/unset TYPE, instead of ServerType or SubscriptionServerType.
Common situations: Frontend bugs sending the wrong touch type; API clients hand-crafting import requests and forgetting to set TYPE; schema/version changes where new TYPE values were added but Import was not updated.
Related errors
- bad request: invalid sub index at index %d: %d
- bad request: invalid index
- juicity: no server address
- tuic: no server address
- dns upstream: invalid response: %w
AI-assisted analysis of v2rayA/v2rayA@71e5442fc5 (2026-09-05).
Data as JSON: /api/errors/c07068acb9e2ecd0.
Report an issue: GitHub.