Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/changelog/122860.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pr: 122860
summary: Improved error message when index field type is invalid
area: Mapping
type: enhancement
issues: []
Original file line number Diff line number Diff line change
Expand Up @@ -214,3 +214,62 @@
index.mode: lookup
index.number_of_shards: 2

---
"Create index with invalid field type":
- requires:
cluster_features: [ "mapper.unknown_field_mapping_update_error_message" ]
reason: "Update error message for unknown field type"

- do:
catch: bad_request
indices.create:
index: test_index
body:
mappings:
properties:
content:
type: invalid

- match: { error.type: "mapper_parsing_exception" }
- match: { error.reason: "Failed to parse mapping: The mapper type [invalid] declared on field [content] does not exist. It might have been created within a future version or requires a plugin to be installed. Check the documentation." }

---
"Create index with invalid runtime field type":
- requires:
cluster_features: [ "mapper.unknown_field_mapping_update_error_message" ]
reason: "Update error message for unknown field type"

- do:
catch: bad_request
indices.create:
index: test_index
body:
mappings:
runtime:
content:
type: invalid

- match: { error.type: "mapper_parsing_exception" }
- match: { error.reason: "Failed to parse mapping: The mapper type [invalid] declared on runtime field [content] does not exist. It might have been created within a future version or requires a plugin to be installed. Check the documentation." }

---
"Create index with invalid multi-field type":
- requires:
cluster_features: [ "mapper.unknown_field_mapping_update_error_message" ]
reason: "Update error message for unknown field type"

- do:
catch: bad_request
indices.create:
index: test_index
body:
mappings:
properties:
city:
type: text
fields:
raw:
type: invalid

- match: { error.type: "mapper_parsing_exception" }
- match: { error.reason: "Failed to parse mapping: The mapper type [invalid] declared on field [raw] does not exist. It might have been created within a future version or requires a plugin to be installed. Check the documentation." }
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ public class MapperFeatures implements FeatureSpecification {
public static final NodeFeature SORT_FIELDS_CHECK_FOR_NESTED_OBJECT_FIX = new NodeFeature("mapper.nested.sorting_fields_check_fix");
public static final NodeFeature DYNAMIC_HANDLING_IN_COPY_TO = new NodeFeature("mapper.copy_to.dynamic_handling");
public static final NodeFeature DOC_VALUES_SKIPPER = new NodeFeature("mapper.doc_values_skipper");
static final NodeFeature UKNOWN_FIELD_MAPPING_UPDATE_ERROR_MESSAGE = new NodeFeature(
"mapper.unknown_field_mapping_update_error_message"
);

@Override
public Set<NodeFeature> getTestFeatures() {
Expand All @@ -54,6 +57,7 @@ public Set<NodeFeature> getTestFeatures() {
TSDB_NESTED_FIELD_SUPPORT,
SourceFieldMapper.SYNTHETIC_RECOVERY_SOURCE,
ObjectMapper.SUBOBJECTS_FALSE_MAPPING_UPDATE_FIX,
UKNOWN_FIELD_MAPPING_UPDATE_ERROR_MESSAGE,
DOC_VALUES_SKIPPER
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,15 @@ protected static void parseProperties(Builder objBuilder, Map<String, Object> pr
}
Mapper.TypeParser typeParser = parserContext.typeParser(type);
if (typeParser == null) {
throw new MapperParsingException("No handler for type [" + type + "] declared on field [" + fieldName + "]");
throw new MapperParsingException(
"The mapper type ["
+ type
+ "] declared on field ["
+ fieldName
+ "] does not exist."
+ " It might have been created within a future version or requires a plugin to be installed."
+ " Check the documentation."
);
}
Mapper.Builder fieldBuilder;
if (objBuilder.subobjects.isPresent() && objBuilder.subobjects.get() != Subobjects.ENABLED) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,15 @@ static Map<String, RuntimeField> parseRuntimeFields(
}
Parser typeParser = parserContext.runtimeFieldParser(type);
if (typeParser == null) {
throw new MapperParsingException("No handler for type [" + type + "] declared on runtime field [" + fieldName + "]");
throw new MapperParsingException(
"The mapper type ["
+ type
+ "] declared on runtime field ["
+ fieldName
+ "] does not exist."
+ " It might have been created within a future version or requires a plugin to be installed."
+ " Check the documentation."
);
}
runtimeFields.put(fieldName, builder.apply(typeParser.parse(fieldName, propNode, parserContext)));
propNode.remove("type");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,15 @@ public static boolean parseMultiField(

Mapper.TypeParser typeParser = parserContext.typeParser(type);
if (typeParser == null) {
throw new MapperParsingException("no handler for type [" + type + "] declared on field [" + multiFieldName + "]");
throw new MapperParsingException(
"The mapper type ["
+ type
+ "] declared on field ["
+ multiFieldName
+ "] does not exist."
+ " It might have been created within a future version or requires a plugin to be installed."
+ " Check the documentation."
);
}
if (typeParser instanceof FieldMapper.TypeParser == false) {
throw new MapperParsingException("Type [" + type + "] cannot be used in multi field");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,13 +313,21 @@ public void testRuntimeSectionMerge() throws IOException {
public void testRuntimeSectionNonRuntimeType() throws IOException {
XContentBuilder mapping = runtimeFieldMapping(builder -> builder.field("type", "unknown"));
MapperParsingException e = expectThrows(MapperParsingException.class, () -> createMapperService(mapping));
assertEquals("Failed to parse mapping: No handler for type [unknown] declared on runtime field [field]", e.getMessage());
assertEquals(
"Failed to parse mapping: The mapper type [unknown] declared on runtime field [field] does not exist."
+ " It might have been created within a future version or requires a plugin to be installed. Check the documentation.",
e.getMessage()
);
}

public void testRuntimeSectionHandlerNotFound() throws IOException {
XContentBuilder mapping = runtimeFieldMapping(builder -> builder.field("type", "unknown"));
MapperParsingException e = expectThrows(MapperParsingException.class, () -> createMapperService(mapping));
assertEquals("Failed to parse mapping: No handler for type [unknown] declared on runtime field [field]", e.getMessage());
assertEquals(
"Failed to parse mapping: The mapper type [unknown] declared on runtime field [field] does not exist."
+ " It might have been created within a future version or requires a plugin to be installed. Check the documentation.",
e.getMessage()
);
}

public void testRuntimeSectionMissingType() throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ setup:
---
"Test transform where source query is invalid":
- do:
catch: /No handler for type \[bad-type\] declared on runtime field \[rt-field\]/
catch: /The mapper type \[bad-type\] declared on runtime field \[rt-field\]/
transform.put_transform:
transform_id: "airline-transform"
body: >
Expand Down