{"record":{"id":"8774a2347796f204","repo":"apache/rocketmq","slug":"offset-0","errorCode":null,"errorMessage":"offset < 0","messagePattern":"offset < 0","errorType":"exception","errorClass":"MQClientException","httpStatus":null,"severity":"error","filePath":"client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java","lineNumber":1051,"sourceCode":"        return pull(mq, subscriptionData, offset, maxNums, this.defaultLitePullConsumer.getConsumerPullTimeoutMillis());\n    }\n\n    private PullResult pull(MessageQueue mq, SubscriptionData subscriptionData, long offset, int maxNums, long timeout)\n        throws MQClientException, RemotingException, MQBrokerException, InterruptedException {\n        return this.pullSyncImpl(mq, subscriptionData, offset, maxNums, true, timeout);\n    }\n\n    private PullResult pullSyncImpl(MessageQueue mq, SubscriptionData subscriptionData, long offset, int maxNums,\n        boolean block,\n        long timeout)\n        throws MQClientException, RemotingException, MQBrokerException, InterruptedException {\n\n        if (null == mq) {\n            throw new MQClientException(\"mq is null\", null);\n        }\n\n        if (offset < 0) {\n            throw new MQClientException(\"offset < 0\", null);\n        }\n\n        if (maxNums <= 0) {\n            throw new MQClientException(\"maxNums <= 0\", null);\n        }\n\n        int sysFlag = PullSysFlag.buildSysFlag(false, block, true, false, true);\n\n        long timeoutMillis = block ? this.defaultLitePullConsumer.getConsumerTimeoutMillisWhenSuspend() : timeout;\n\n        boolean isTagType = ExpressionType.isTagType(subscriptionData.getExpressionType());\n        PullResult pullResult = this.pullAPIWrapper.pullKernelImpl(\n            mq,\n            subscriptionData.getSubString(),\n            subscriptionData.getExpressionType(),\n            isTagType ? 0L : subscriptionData.getSubVersion(),\n            offset,\n            maxNums,","sourceCodeStart":1033,"sourceCodeEnd":1069,"githubUrl":"https://github.com/apache/rocketmq/blob/293f5885719fc4aa3619446a1900f58ccfcfdd29/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java#L1033-L1069","documentation":"pullSyncImpl throws MQClientException(\"offset < 0\") when the requested starting offset is negative. Pull always begins at an absolute committed offset; negative values are not valid positions (there is no 'newest'/'oldest' sentinel offset in this API — those are chosen via fromWhere at assignment time).","triggerScenarios":"consumer.pull(q, expr, -1, maxNums, timeout); passing a computed offset that is -1 as a 'not found' sentinel from your own offset store.","commonSituations":"Your own offset store returning -1 as a 'no offset yet' sentinel and feeding it straight to pull; reusing Kafka's offset semantics where -1 means latest.","solutions":["Resolve a real offset first via fetchConsumeOffset / minOffset before pulling","Map your own 'no offset' sentinel (-1) to consumer.minOffset(q) or the configured fromWhere policy"],"exampleFix":"// before\nlong off = myStore.get(q); // -1 when absent\nconsumer.pull(q, \"*\", off, 32, 3000);\n\n// after\nlong off = myStore.containsKey(q) ? myStore.get(q) : consumer.minOffset(q);\nconsumer.pull(q, \"*\", Math.max(0, off), 32, 3000);","handlingStrategy":"validation","validationCode":"long safeOffset = Math.max(0, offset);\n// or resolve a real start offset first:\nif (offset < 0) offset = consumer.minOffset(q);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not use -1 as a pull offset sentinel — map it to minOffset or your fromWhere policy first","Always fetch a valid committed offset before pulling"],"tags":["rocketmq","consumer","pull","offset","validation"],"backgroundTag":null,"analyzedSha":"293f5885719fc4aa3619446a1900f58ccfcfdd29","analyzedAt":"2026-08-14T11:50:13.822Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}