{"record":{"id":"2c1b3c33da11e86c","repo":"apache/skywalking","slug":"can-t-split-service-id-into-2-parts","errorCode":null,"errorMessage":"Can't split service id into 2 parts, {}","messagePattern":"Can't split service id into 2 parts, (.+?)","errorType":"exception","errorClass":"UnexpectedException","httpStatus":null,"severity":"error","filePath":"oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/IDManager.java","lineNumber":59,"sourceCode":"        /**\n         * @param name     service name\n         * @param isNormal `true` represents this service is detected by an agent. `false` represents this service is\n         *                 conjectured by telemetry data collected from agents on/in the `normal` service.\n         */\n        public static String buildId(String name, boolean isNormal) {\n            if (StringUtil.isBlank(name)) {\n                name = Const.BLANK_ENTITY_NAME;\n            }\n            return encode(name) + Const.SERVICE_ID_CONNECTOR + BooleanUtils.booleanToValue(isNormal);\n        }\n\n        /**\n         * @return service ID object decoded from {@link #buildId(String, boolean)} result\n         */\n        public static ServiceIDDefinition analysisId(String id) {\n            final String[] strings = id.split(Const.SERVICE_ID_PARSER_SPLIT);\n            if (strings.length != 2) {\n                throw new UnexpectedException(\"Can't split service id into 2 parts, \" + id);\n            }\n            return new ServiceID.ServiceIDDefinition(\n                decode(strings[0]),\n                BooleanUtils.valueToBoolean(Integer.parseInt(strings[1]))\n            );\n        }\n\n        /**\n         * @return encoded service relation id\n         */\n        public static String buildRelationId(ServiceRelationDefine define) {\n            return define.sourceId + Const.RELATION_ID_CONNECTOR + define.destId;\n        }\n\n        /**\n         * @return encoded service hierarchy relation id\n         */\n        public static String buildServiceHierarchyRelationId(ServiceHierarchyRelationDefine define) {","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/apache/skywalking/blob/102af09b4a56064e22050dded10e2c52e490d040/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/IDManager.java#L41-L77","documentation":"UnexpectedException thrown by IDManager.ServiceID.analysisId(String) when a service ID string cannot be split into exactly 2 parts by Const.SERVICE_ID_PARSER_SPLIT. Service IDs are built by buildId(name, isNormal) as encode(name) + '.' + booleanValue(0/1); analysisId is the inverse and treats any other shape as data corruption. The offending id is included in the message.","triggerScenarios":"Calling ServiceID.analysisId on a string that is not a buildId product: a raw service name without the connector, an id built with a different connector constant, an id with extra '.' segments because the encoded name leaks an unencoded '.', or null/empty passed in.","commonSituations":"Custom storage/receiver code re-implementing id assembly instead of calling buildId; version skew where a producer encodes differently than the consumer decodes; unit tests feeding hand-crafted ids; data written by an old OAP being read by new code after encoding changes.","solutions":["Always build ids with IDManager.ServiceID.buildId(name, isNormal) and only pass those to analysisId","If hand-constructing, match the exact format: URL-encoded name + Const.SERVICE_ID_CONNECTOR + '0'|'1'","Log the failing id (it is in the message) and trace which writer produced it — usually a non-standard producer","On version-skew migrations, reindex/rewrite stored ids or read them with the old format"],"exampleFix":"// before\nServiceIDDefinition def = IDManager.ServiceID.analysisId(serviceName); // raw name -> throws\n\n// after\nString id = IDManager.ServiceID.buildId(serviceName, true);\nServiceIDDefinition def = IDManager.ServiceID.analysisId(id);","handlingStrategy":"type-guard","validationCode":"String PATTERN = \"^[^.]+\\\\.[01]$\"; // encoded-name '.' 0|1\nif (id == null || !id.matches(PATTERN)) {\n    throw new IllegalArgumentException(\"Not a service id produced by IDManager.ServiceID.buildId: \" + id);\n}","typeGuard":"boolean isServiceId(String id) {\n    return id != null && id.matches(\"^[^.]+\\\\.[01]$\");\n}","tryCatchPattern":"try {\n    ServiceIDDefinition def = IDManager.ServiceID.analysisId(id);\n} catch (UnexpectedException e) {\n    LOGGER.warn(\"Skipping malformed service id: {}\", id, e);\n}","preventionTips":["Never hand-assemble ids; always round-trip through buildId/analysisId from the same IDManager version","Keep the id format constant across services — never store ids from a newer OAP into data read by an older one","In tests, generate ids only via buildId"],"tags":["id-management","data-corruption","parsing","oap-server"],"backgroundTag":null,"analyzedSha":"102af09b4a56064e22050dded10e2c52e490d040","analyzedAt":"2026-08-14T10:47:52.647Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}