--- title: "failed to get type [type] and id [id] - 获取 type 和 ID 失败" date: 2026-04-04 lastmod: 2026-04-04 description: "failed to get type [type] and id [id] 表示 Elasticsearch 在旧版 typed get 流程中读取指定 type 和 id 的 stored fields 时发生 IOException,通常是段文件损坏、磁盘 I/O 故障或分片状态异常导致,本文详解排查与修复方法。" tags: ["typed get", "stored fields", "legacy API", "文档读取", "type", "IOException", "旧版API", "ElasticsearchException"] summary: "适用版本: 5.6-7.x(typed API 已废弃,8.x 已移除) 1. 错误异常的基本描述 # Failed to get type [type] and id [id] 出现在旧版带 type 的 Get API 路径中,表示 Elasticsearch 在通过 Lucene reader 读取该文档的 stored fields 时失败。它与 typeless 版本的 Failed to get id [id] 类似,但这里仍处于历史的 typed document 读取模型下,涉及 type 和 id 两个维度。 常见现象 # 旧版接口如 GET /index/type/id 返回 500 内部服务器错误。 问题通常只影响少量文档或个别分片,其他文档可以正常读取。 日志里常带 IOException、reader 读取失败或段文件异常,例如 read past EOF 或 Corrupt index。 如果是批量查询(_mget)中使用 typed 格式,只有特定 type 和 id 的组合会失败。 在 Elasticsearch 7." --- > **适用版本:** 5.6-7.x(typed API 已废弃,8.x 已移除) ## 1. 错误异常的基本描述 `Failed to get type [type] and id [id]` 出现在旧版带 type 的 Get API 路径中,表示 Elasticsearch 在通过 Lucene reader 读取该文档的 stored fields 时失败。它与 typeless 版本的 `Failed to get id [id]` 类似,但这里仍处于历史的 typed document 读取模型下,涉及 type 和 id 两个维度。 ### 常见现象 - 旧版接口如 `GET /index/type/id` 返回 `500` 内部服务器错误。 - 问题通常只影响少量文档或个别分片,其他文档可以正常读取。 - 日志里常带 `IOException`、reader 读取失败或段文件异常,例如 `read past EOF` 或 `Corrupt index`。 - 如果是批量查询(`_mget`)中使用 typed 格式,只有特定 type 和 id 的组合会失败。 - 在 Elasticsearch 7.x 中,虽然默认不推荐,但 typed API 仍然可用;在 8.x 中,type 已被完全移除,此错误不再出现(会返回不同的错误)。 ### 典型报错与异常栈 常见日志形态通常类似下面这样: ```text ElasticsearchException: Failed to get type [my_type] and id [abc123] Caused by: java.io.IOException: read past EOF at org.apache.lucene.index.SegmentReader.document(SegmentReader.java:...) ``` 或者段文件损坏: ```text ElasticsearchException: Failed to get type [_doc] and id [xyz789] Caused by: java.io.IOException: Corrupt index at org.apache.lucene.codecs.StoredFieldsReader... ``` 或者文件句柄问题: ```text ElasticsearchException: Failed to get type [logs] and id [doc456] Caused by: java.io.IOException: Too many open files ``` ## 2. 为什么会发生这个错误 `Failed to get type [type] and id [id]` 的根因是"在旧版 typed Get 请求中,读取文档 stored fields 失败"。从日志片段看,异常发生在 `docIdAndVersion.reader.document(docIdAndVersion.docId, fieldVisitor)`。这一步直接从底层 reader 读取目标文档字段;只要字段文件、reader 或底层存储异常,就会包装成当前错误。 常见原因通常包括: - **旧索引段文件损坏**:历史 typed 索引的 Lucene 段文件(`.fdt`、`.fdx`、`.si` 等)损坏或数据不完整。 - **分片状态不稳定**:分片正在恢复、迁移或关闭,导致 reader 状态异常或不一致。 - **底层存储瞬时不可用**:磁盘故障、文件系统错误、网络存储(如 NFS)断开,导致 Lucene 读取失败。 - **节点资源异常**:磁盘空间不足、文件句柄耗尽(too many open files)、I/O 等待过高。 - **索引升级遗留问题**:从旧版本(如 5.x、6.x)升级到新版本(如 7.x)后,历史 typed 索引在升级过程中遗留了底层读取问题。 - **type 相关兼容性问题**:在版本迁移过程中,type 的处理逻辑可能发生变化,导致某些历史数据读取失败。 - **段合并异常**:在段合并过程中,某些段文件被意外删除或覆盖,影响 typed 文档的读取。 ## 3. 如何排查和解决这个异常和解决这个异常 建议按"先确认 API 版本、再定位影响范围、后检查存储健康"的顺序处理: 1. **确认 API 版本**:检查调用的是否是旧版 typed API 或内部兼容路径,考虑迁移到 typeless API。 ```bash # 旧版 typed API(不推荐) curl -X GET "localhost:9200/my_index/my_type/my_id" # 新版 typeless API(推荐) curl -X GET "localhost:9200/my_index/_doc/my_id" ``` 2. **检查异常影响范围**:确认问题是否只影响特定 type、特定文档或特定分片。 ```bash # 查看索引中的 type 分布(7.x 中通常只有 _doc) curl -X GET "localhost:9200/my_index/_mapping?pretty" # 尝试获取其他文档,确认是否只有特定文档失败 curl -X GET "localhost:9200/my_index/_doc/other_id" ``` 3. **查看节点日志**:从 Elasticsearch 节点日志中找到这个异常对应的底层 `caused by`。 ```bash # 查看相关错误日志 grep -r "Failed to get type" /var/log/elasticsearch/ grep -r "IOException" /var/log/elasticsearch/ | tail -50 ``` 4. **检查分片状态**:确认分片是否处于恢复、迁移、关闭或异常状态。 ```bash # 查看分片分配和状态 curl -X GET "localhost:9200/_cat/shards/my_index?v" # 查看未分配分片的原因 curl -X GET "localhost:9200/_cluster/allocation/explain?pretty" ``` 5. **检查磁盘和文件系统**:查看磁盘空间、I/O 状态和文件句柄使用情况。 ```bash # 检查磁盘空间 df -h # 检查磁盘 I/O 错误 dmesg | grep -i "error\|io\|ext4\|xfs" # 检查文件句柄使用 lsof -p $(pgrep -f elasticsearch) | wc -l ``` 6. **检查索引升级历史**:如果索引是从旧版本升级而来,确认是否存在旧索引长期遗留问题。 ```bash # 查看索引创建版本(通过 settings) curl -X GET "localhost:9200/my_index/_settings?pretty" | grep "version" ``` ### 排查时需要注意的问题 - 这个错误出现在旧版 typed API 中,如果可能,建议迁移到 typeless API(去掉 URL 中的 type 部分)。 - 如果问题只出现在特定 type 上,可能是该 type 对应的数据有问题,需要重点检查。 - 对于历史 typed 索引,需要考虑是否值得修复,还是直接迁移到新索引(typeless)。 ## 4. 如何解决这个错误 ### 常用修复思路 - **迁移到 typeless API**:如果使用的是 7.x 或更高版本,建议迁移到 typeless API,避免 typed API 的兼容性问题。 ```bash # 旧版 typed API(避免使用) curl -X GET "localhost:9200/my_index/my_type/my_id" # 新版 typeless API(推荐使用) curl -X GET "localhost:9200/my_index/_doc/my_id" ``` - **通过副本恢复分片**:如果主分片数据损坏,可以尝试分配副本分片来恢复。 ```bash # 尝试分配副本分片 curl -X POST "localhost:9200/_cluster/reroute" -H 'Content-Type: application/json' -d' { "commands": [ { "allocate_replica": { "index": "my_index", "shard": 0, "node": "target_node_name" } } ] } ' ``` - **重建索引**:对历史 typed 索引,考虑重建为 typeless 索引,同时修复数据问题。 ```bash # 重建索引(从旧索引到新索引) curl -X POST "localhost:9200/_reindex?pretty" -H 'Content-Type: application/json' -d' { "source": { "index": "old_typed_index" }, "dest": { "index": "new_typeless_index" } } ' ``` - **从快照恢复**:如果有快照备份,可以从快照恢复受损的索引。 ```bash # 从快照恢复索引 curl -X POST "localhost:9200/_snapshot/my_backup/snapshot_1/_restore" -H 'Content-Type: application/json' -d' { "indices": "my_index", "ignore_unavailable": true, "include_global_state": false } ' ``` - **删除损坏文档**:如果只有个别文档损坏,可以尝试删除后重新索引。 ```bash # 删除损坏的文档(需要知道文档 ID) curl -X DELETE "localhost:9200/my_index/my_type/my_id" ``` ### 后续注意事项与推荐建议 - 如果仍在使用 typed API(Elasticsearch 7.x),建议尽快迁移到 typeless API,为升级到 8.x 做准备。 - 对于历史 typed 索引,评估是否需要重建为 typeless 索引,避免后续升级风险。 - 定期监控磁盘空间、文件句柄和 I/O 等待指标,在资源耗尽前提前预警。 - 为重要索引配置至少 1 个副本分片,确保在主分片故障时可以快速恢复。 ### 借助 INFINI 产品提升排障效率 - [INFINI Console](https://docs.infinilabs.com/console/main/) 适合查看集群的索引状态、分片分配、节点指标和错误趋势,帮助快速判断 `Failed to get type [type] and id [id]` 是局部数据问题还是系统性存储问题,并提供可视化的索引管理和重建功能。 - [INFINI Gateway](https://docs.infinilabs.com/gateway/main/) 适合部署在 Elasticsearch 前面做请求观测和流量治理,可以记录所有 Get 请求的详细日志,帮助定位是 typed API 问题还是数据问题,同时提供请求缓存功能减少重复的读取操作。 - 建议将索引健康状态、分片分配和存储层指标统一接入监控面板,结合 INFINI Console 的告警功能,在分片异常或存储故障时及时通知。 ## 5. 小结 `Failed to get type [type] and id [id]` 是典型的旧版 typed get 底层读取异常。处理时既要看当前 I/O 和分片状态,也要考虑索引历史和版本兼容包袱。如果可能,建议迁移到 typeless API 并重建历史索引,从根本上避免 typed API 的兼容性问题。 只要把存储监控、副本策略和版本升级规划固定下来,大多数 typed API 读取类异常都可以被有效解决,也更容易通过 INFINI Console 和 INFINI Gateway 实现持续防护。 ## 相关错误 - [failed-to-get-type-type-and-id-id-with-includes-excludes-set-how-to-solve-this-elasticsearch-exception](/knowledge-base/elasticsearch_error/failed-to-get-type-type-and-id-id-with-includes-excludes-set-how-to-solve-this-elasticsearch-exception/) - [failed-to-get-id-id-how-to-solve-this-elasticsearch-exception](/knowledge-base/elasticsearch_error/failed-to-get-id-id-how-to-solve-this-elasticsearch-exception/) - [failed-to-get-binary-value-how-to-solve-this-elasticsearch-exception](/knowledge-base/elasticsearch_error/failed-to-get-binary-value-how-to-solve-this-elasticsearch-exception/) - [failed-to-read-value-how-to-solve-this-elasticsearch-exception](/knowledge-base/elasticsearch_error/failed-to-read-value-how-to-solve-this-elasticsearch-exception/) ## 参考文档 - [Elasticsearch Get API 官方文档](https://www.elastic.co/guide/en/elasticsearch/reference/7.17/docs-get.html) - [Elasticsearch Removal of Types 官方文档](https://www.elastic.co/guide/en/elasticsearch/reference/7.17/removal-of-types.html) - [Elasticsearch 索引快照官方文档](https://www.elastic.co/guide/en/elasticsearch/reference/7.17/snapshot-restore.html) - [INFINI Console 文档](https://docs.infinilabs.com/console/main/) - [INFINI Gateway 文档](https://docs.infinilabs.com/gateway/main/) ## 附:日志上下文 下面保留当前页面中的源码或日志片段,便于继续结合异常调用栈定位问题: ```java FieldsVisitor fieldVisitor = buildFieldsVisitors(storedFields; fetchSourceContext); if (fieldVisitor != null) { try { docIdAndVersion.reader.document(docIdAndVersion.docId; fieldVisitor); } catch (IOException e) { throw new ElasticsearchException("Failed to get type [" + type + "] and id [" + id + "]"; e); } source = fieldVisitor.source(); // put stored fields into result objects if (fieldVisitor.fields().isEmpty() == false) { ```