{"record":{"id":"693c2342cc8d6bec","repo":"MemPalace/mempalace","slug":"pass-inline-text-or-a-file-not-both","errorCode":null,"errorMessage":"pass inline text or a file, not both","messagePattern":"pass inline text or a file, not both","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"mempalace/cli.py","lineNumber":1494,"sourceCode":"    \"\"\"\n    buffer = getattr(sys.stdout, \"buffer\", None)\n    if buffer is None:\n        sys.stdout.write(content)\n        return\n    sys.stdout.flush()\n    buffer.write(content.encode(\"utf-8\"))\n    buffer.flush()\n\n\ndef _read_text_arg(inline, file_arg, default=\"\"):\n    \"\"\"Resolve inline text vs --*-file (with '-' meaning stdin).\n\n    File and stdin reads are byte-exact (see :func:`_read_stdin_exact`):\n    the logstream's contract is verbatim content, so line endings must\n    reach the store exactly as the author wrote them.\n    \"\"\"\n    if inline is not None and file_arg is not None:\n        raise ValueError(\"pass inline text or a file, not both\")\n    if file_arg is not None:\n        if file_arg == \"-\":\n            return _read_stdin_exact()\n        return Path(os.path.expanduser(file_arg)).read_bytes().decode(\"utf-8\")\n    if inline is not None:\n        return inline\n    return default\n\n\ndef _parse_metadata_arg(raw):\n    import json\n\n    if raw is None:\n        return None\n    try:\n        value = json.loads(raw)\n    except ValueError as exc:\n        raise ValueError(f\"--metadata is not valid JSON: {exc}\") from None","sourceCodeStart":1476,"sourceCodeEnd":1512,"githubUrl":"https://github.com/MemPalace/mempalace/blob/06cb6987f02610784fefbad4b2bd5d026d164ba6/mempalace/cli.py#L1476-L1512","documentation":"Raised by _read_text_arg() in the CLI when both an inline text argument and a file-path argument are supplied for the same piece of content. The CLI logstream commands (e.g. diary/log/event append) accept either inline text or a --*-file path (including '-' for stdin), never both; the function raises ValueError to avoid ambiguity about which content wins. The logstream contract is verbatim byte-exact content, so silently preferring one source would risk data loss.","triggerScenarios":"Calling any CLI subcommand whose handler routes through _read_text_arg(inline, file_arg) with both positional inline text and a --file option set, e.g. `mempalace diary add \"some text\" --file notes.txt`.","commonSituations":"Shell scripts that pass a default positional string and a --file flag unconditionally; copy-pasting a command template and leaving the placeholder text in place alongside the file; CI pipelines that template both arguments.","solutions":["Pass the content either inline or via the file option, not both — drop one of the two arguments","If the content is on stdin, use --file - and remove the inline text","Guard wrapper scripts: only set the file flag when the inline variable is empty"],"exampleFix":"# before\nmempalace diary add \"my note\" --file note.txt\n\n# after\nmempalace diary add --file note.txt","handlingStrategy":"validation","validationCode":"# Before calling a logstream command that routes through _read_text_arg:\nif inline_text is not None and file_arg is not None:\n    raise SystemExit(\"pass either inline text or --file, not both\")\n# Prefer one canonical source in scripts:\ntext = Path(file_arg).read_text() if file_arg else inline_text","typeGuard":null,"tryCatchPattern":"try:\n    text = _read_text_arg(inline, file_arg)\nexcept ValueError as exc:\n    if \"not both\" in str(exc):\n        file_arg = None  # resolve ambiguity explicitly, then retry\n        text = _read_text_arg(inline, file_arg)\n    else:\n        raise","preventionTips":["In wrapper scripts, make inline and --file mutually exclusive (argparse mutually exclusive group)","Never template both the positional text and --file flag unconditionally","Use --file - for stdin so pipelines never need inline text"],"tags":["cli","validation","arguments","mempalace"],"backgroundTag":null,"analyzedSha":"06cb6987f02610784fefbad4b2bd5d026d164ba6","analyzedAt":"2026-08-15T03:03:36.213Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}