{"record":{"id":"70b0646b5300aa07","repo":"XTLS/Xray-core","slug":"failed-to-create-hosts","errorCode":null,"errorMessage":"failed to create hosts","messagePattern":"failed to create hosts","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/dns/dns.go","lineNumber":86,"sourceCode":"\tcase QueryStrategy_USE_IP4:\n\t\tipOption = dns.IPOption{\n\t\t\tIPv4Enable: true,\n\t\t\tIPv6Enable: false,\n\t\t\tFakeEnable: false,\n\t\t}\n\tcase QueryStrategy_USE_IP6:\n\t\tipOption = dns.IPOption{\n\t\t\tIPv4Enable: false,\n\t\t\tIPv6Enable: true,\n\t\t\tFakeEnable: false,\n\t\t}\n\tdefault:\n\t\treturn nil, errors.New(\"unexpected query strategy \", config.QueryStrategy)\n\t}\n\n\thosts, err := NewStaticHosts(config.StaticHosts)\n\tif err != nil {\n\t\treturn nil, errors.New(\"failed to create hosts\").Base(err)\n\t}\n\n\tdefaultTag := config.Tag\n\tif len(config.Tag) == 0 {\n\t\tdefaultTag = generateRandomTag()\n\t}\n\n\tclients := make([]*Client, 0, len(config.NameServer))\n\tmatcherInfos := make([]*DomainMatcherInfo, 0)\n\teffectiveRules := make([]*geodata.DomainRule, 0)\n\n\tfor _, ns := range config.NameServer {\n\t\tclientIdx := len(clients)\n\t\tupdateRules := func(isLocalNameServer bool) {\n\t\t\t// Prioritize local domains with specific TLDs or those without any dot for the local DNS\n\t\t\tif isLocalNameServer {\n\t\t\t\teffectiveRules = append(effectiveRules, localTLDsAndDotlessDomainsRules...)\n\t\t\t\tfor _, rule := range localTLDsAndDotlessDomainsRules {","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/app/dns/dns.go#L68-L104","documentation":"After selecting a target length, writePaddingTurnWithBuffer computes recordLength = targetLength - prefixLength and requires it to be at least 1, because a padding record must contain its varint header plus payload. This error means the selected variant's total length (or a send-range draw) is not larger than the prefix that was already sent inside it, leaving no room for a record.","triggerScenarios":"A variant on turn 0 whose chunk sum <= firstTurnPrefixLength, or a sendMinLength/sendMaxLength draw <= prefixLength. Note validation only guarantees minLength - prefix >= 1 for turn 0, so send-range draws below minLength (impossible after validation) or unvalidated direct writes trigger this.","commonSituations":"Calling writePaddingTurn directly with a short variant and a large prefix; a schedule where a variant equals the prefix length exactly; test scaffolding that passes prefixLength larger than the turn's target length.","solutions":["Ensure every selectable variant/send-range draw is strictly longer than prefixLength","For turn 0, keep minLength (and every variant total) >= firstTurnPrefixLength + 1","Route writes through runPaddingSchedule so the up-front bounds check catches the misconfiguration deterministically"],"exampleFix":"// before: variant total 64 with prefix 64 leaves no record\npaddingVariant{chunks: []int{64}}\n// after\npaddingVariant{chunks: []int{64, 256}}","handlingStrategy":"validation","validationCode":"minSelectable := turn.minLength\nif len(turn.variants) > 0 {\n    minSelectable = math.MaxInt\n    for _, v := range turn.variants {\n        if l := paddingVariantLength(v); l < minSelectable {\n            minSelectable = l\n        }\n    }\n}\nif minSelectable-prefixLength < 1 {\n    return errors.New(\"turn cannot fit prefix plus a record\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep every variant total and the send range strictly greater than the prefix","Validate via runPaddingSchedule instead of calling write APIs directly"],"tags":["padding","validation","variants","prefix","xmc"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}