ComposioHQ/composio · warning · Error
Use only one of before or after.
Error message
Use only one of before or after.
What it means
The beeper-imessage thread listing tools accept before and after cursors for pagination, but they are mutually exclusive — you may pass at most one. Passing both is rejected because the underlying CLI cannot apply two conflicting cursor directions at once.
Source
Thrown at ts/packages/cli-local-tools/src/toolkits/beeper-imessage.ts:158
return messages[0];
};
const buildGlobalArgs = (input: Record<string, unknown>): string[] => {
const args: string[] = [];
const dataDir = optionalString(input.dataDir);
if (dataDir) args.push('--data-dir', dataDir);
if (input.useSecondaryInstance === false) args.push('--no-use-secondary-instance');
// Local tools are one-shot calls. Avoid keeping DB event watchers open unless a
// future streaming tool explicitly opts in.
args.push('--no-events');
if (input.verbose === true) args.push('--verbose');
return args;
};
const withCursorArgs = (input: Record<string, unknown>, args: string[]): string[] => {
const before = optionalString(input.before);
const after = optionalString(input.after);
if (before && after) throw new Error('Use only one of before or after.');
if (before) args.push('--before', before);
if (after) args.push('--after', after);
return args;
};
const stripAnsi = (text: string): string => text.replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, '');
const parseImessageCliOutput = (
commandName: string,
stdout: string,
stderr: string
): LocalExecutionResult => {
const cleanStdout = stripAnsi(stdout);
const lines = cleanStdout.split(/\r?\n/);
const okIndex = lines.findIndex(line => /^\[\d+\] ok /.test(line));
const okLine = okIndex >= 0 ? lines[okIndex] : undefined;
const match = okLine?.match(/^\[(\d+)\] ok \S+ \((\d+(?:\.\d+)?)ms\)$/);
View on GitHub (pinned to 64b1b85502)
Solutions
- Pass only one cursor: before OR after
- Clear the opposite field when reusing a params object across pages
- Use the returned next-cursor value for the next page rather than tracking both
Example fix
// before
raw({ before: 'cursorA', after: 'cursorB', limit: 50 });
// after
raw({ after: 'cursorB', limit: 50 }); Defensive patterns
Strategy: validation
Validate before calling
const hasBoth = input.before != null && input.after != null;
if (hasBoth) throw new RangeError('pick one cursor'); Type guard
const singleCursor = (i: { before?: string; after?: string }) =>
(i.before ? 1 : 0) + (i.after ? 1 : 0) <= 1; Try / catch
try { ... } catch (e) { if (e.message === 'Use only one of before or after.') dropOneCursorAndRetry(); } Prevention
- Pass only the cursor returned by the previous page
- Delete stale cursor fields when reusing param objects
When it happens
Trigger: Calling page/raw list tools with both input.before and input.after set, e.g. copying a pagination loop that fills both cursors; LLM tool calls that populate every optional field.
Common situations: Auto-generated tool calls from LLMs filling all optional params; refactors that merge two pagination calls into one.
Related errors
- Provide query or recipients to find an iMessage thread.
- Invalid arguments for local tool ${resolution.finalSlug}: ${
- Failed to validate list options
- Could not determine a home directory to store the Composio c
- Cache directory {directory} is not writable please provide a
AI-assisted analysis of ComposioHQ/composio@64b1b85502 (2026-08-28).
Data as JSON: /api/errors/5d859e33bf86fa50.
Report an issue: GitHub.