tomchristie: Fantastic stuff, thanks! Great spot wrt. trailing `\r` behaviour too, I've resolved that in #1075.
diff --git a/httpx/_decoders.py b/httpx/_decoders.py
index 2a2e703..1ea47b0 100644
--- a/httpx/_decoders.py
+++ b/httpx/_decoders.py
@@ -261,7 +261,7 @@ class LineDecoder:
                     text = text[idx + 1 :]
                     break
                 elif next_char is None:
-                    self.buffer = text
+                    self.buffer += text
                     text = ""
                     break
 
diff --git a/requirements.txt b/requirements.txt
index 246a08e..4260706 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -31,4 +31,4 @@ trustme
 uvicorn
 seed-isort-config
 
-attrs>=19.2  # See: https://github.com/encode/httpx/pull/566#issuecomment-559862665
+attrs>=19.3.0  # See: https://github.com/encode/httpx/pull/566#issuecomment-559862665

aiter_lines() doesn't return full lines that span multiple chunks
<https://gist.github.com/scr-oath/aa76d200222a0409d09a0d6feb1a13e2> shows an example setup using cherry.py as server that just outputs two lines - the json is big enough to be sent in two chunks; httpx aiter_lines() gets confused and sends data from the middle of the json line - seems to skip the starting part - which was most likely sent in a chunk without a newline

### test-httpx.py
```python
import asyncio
import json

import httpx


class TestHttpx:
    def __init__(self):
        pass

    async def __call__(self):
        http_client = httpx.AsyncClient()
        async with http_client.stream(method="GET", url='http://localhost:8080/lines') as response:
            is_message = True
            async for line in response.aiter_lines():
                is_message = not is_message
                if is_message:
                    message = json.loads(line)
                    print(message)


def main():
    test_httpx = TestHttpx()
    asyncio.run(test_httpx())


if __name__ == '__main__':
    main()
```
diff --git a/tests/test_decoders.py b/tests/test_decoders.py
index 9f2fa51..89c545b 100644
--- a/tests/test_decoders.py
+++ b/tests/test_decoders.py
@@ -225,6 +225,15 @@ def test_line_decoder_nl():
     assert decoder.decode("a\n\nb\nc\n") == ["a\n", "\n", "b\n", "c\n"]
     assert decoder.flush() == []
 
+    # Issue #1033
+    decoder = LineDecoder()
+    assert decoder.decode("") == []
+    assert decoder.decode("12345\n") == ["12345\n"]
+    assert decoder.decode("foo ") == []
+    assert decoder.decode("bar ") == []
+    assert decoder.decode("baz\n") == ["foo bar baz\n"]
+    assert decoder.flush() == []
+
 
 def test_line_decoder_cr():
     decoder = LineDecoder()
@@ -237,6 +246,16 @@ def test_line_decoder_cr():
     assert decoder.decode("a\r\rb\rc\r") == ["a\n", "\n", "b\n"]
     assert decoder.flush() == ["c\n"]
 
+    # Issue #1033
+    # TODO: This seems like another bug; fix expectations and results.
+    decoder = LineDecoder()
+    assert decoder.decode("") == []
+    assert decoder.decode("12345\r") == []
+    assert decoder.decode("foo ") == []
+    assert decoder.decode("bar ") == []
+    assert decoder.decode("baz\r") == []
+    assert decoder.flush() == ["12345\rfoo bar baz\n"]
+
 
 def test_line_decoder_crnl():
     decoder = LineDecoder()
@@ -255,6 +274,15 @@ def test_line_decoder_crnl():
     assert decoder.decode("\n\r\nb\r\nc") == ["a\n", "\n", "b\n"]
     assert decoder.flush() == ["c"]
 
+    # Issue #1033
+    decoder = LineDecoder()
+    assert decoder.decode("") == []
+    assert decoder.decode("12345\r\n") == ["12345\n"]
+    assert decoder.decode("foo ") == []
+    assert decoder.decode("bar ") == []
+    assert decoder.decode("baz\r\n") == ["foo bar baz\n"]
+    assert decoder.flush() == []
+
 
 def test_invalid_content_encoding_header():
     headers = [(b"Content-Encoding", b"invalid-header")]

pip install -e .
parse_log_pytest
requirements.txt
3.9
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
aspy.refactor-imports==3.0.2
async-generator==1.10
attrs==25.3.0
autoflake==2.3.1
babel==2.17.0
backports.tarfile==1.2.0
backrefs==5.8
black==25.1.0
brotlipy==0.7.0
certifi==2025.1.31
cffi==1.17.1
chardet==3.0.4
charset-normalizer==3.4.1
click==8.1.8
colorama==0.4.6
coverage==7.8.0
cryptography==44.0.2
docutils==0.21.2
exceptiongroup==1.2.2
flake8==7.2.0
flake8-bugbear==24.12.12
flake8-pie==0.16.0
ghp-import==2.1.0
h11==0.9.0
h2==3.2.0
hpack==3.0.0
hstspreload==2025.1.1
httpcore==0.9.1
-e git+https://github.com/encode/httpx.git@27b0dbc22da1424a020c2bb769c81490f39ce283#egg=httpx
hyperframe==5.2.0
id==1.5.0
idna==2.10
importlib_metadata==8.6.1
iniconfig==2.1.0
isort==5.13.2
jaraco.classes==3.4.0
jaraco.context==6.0.1
jaraco.functools==4.1.0
jeepney==0.9.0
Jinja2==3.1.6
keyring==25.6.0
Markdown==3.7
markdown-it-py==3.0.0
MarkupSafe==3.0.2
mccabe==0.7.0
mdurl==0.1.2
mergedeep==1.3.4
mkautodoc==0.2.0
mkdocs==1.6.1
mkdocs-get-deps==0.2.0
mkdocs-material==9.6.10
mkdocs-material-extensions==1.3.1
more-itertools==10.6.0
mypy==1.15.0
mypy-extensions==1.0.0
nh3==0.2.21
outcome==1.3.0.post0
packaging==24.2
paginate==0.5.7
pathspec==0.12.1
platformdirs==4.3.7
pluggy==1.5.0
pycodestyle==2.13.0
pycparser==2.22
pyflakes==3.3.2
Pygments==2.19.1
pymdown-extensions==10.14.3
pytest==8.3.5
pytest-asyncio==0.26.0
pytest-cov==6.0.0
pytest-trio==0.8.0
python-dateutil==2.9.0.post0
PyYAML==6.0.2
pyyaml_env_tag==0.1
readme_renderer==44.0
requests==2.32.3
requests-toolbelt==1.0.0
rfc3986==1.5.0
rich==14.0.0
SecretStorage==3.3.3
seed-isort-config==2.2.0
six==1.17.0
sniffio==1.3.1
sortedcontainers==2.4.0
tomli==2.2.1
trio==0.29.0
trio-typing==0.10.0
trustme==1.2.1
twine==6.1.0
typing_extensions==4.13.0
urllib3==2.3.0
uvicorn==0.34.0
watchdog==6.0.0
zipp==3.21.0

name: httpx
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - aspy-refactor-imports==3.0.2
      - async-generator==1.10
      - attrs==25.3.0
      - autoflake==2.3.1
      - babel==2.17.0
      - backports-tarfile==1.2.0
      - backrefs==5.8
      - black==25.1.0
      - brotlipy==0.7.0
      - certifi==2025.1.31
      - cffi==1.17.1
      - chardet==3.0.4
      - charset-normalizer==3.4.1
      - click==8.1.8
      - colorama==0.4.6
      - coverage==7.8.0
      - cryptography==44.0.2
      - docutils==0.21.2
      - exceptiongroup==1.2.2
      - flake8==7.2.0
      - flake8-bugbear==24.12.12
      - flake8-pie==0.16.0
      - ghp-import==2.1.0
      - h11==0.9.0
      - h2==3.2.0
      - hpack==3.0.0
      - hstspreload==2025.1.1
      - httpcore==0.9.1
      - hyperframe==5.2.0
      - id==1.5.0
      - idna==2.10
      - importlib-metadata==8.6.1
      - iniconfig==2.1.0
      - isort==5.13.2
      - jaraco-classes==3.4.0
      - jaraco-context==6.0.1
      - jaraco-functools==4.1.0
      - jeepney==0.9.0
      - jinja2==3.1.6
      - keyring==25.6.0
      - markdown==3.7
      - markdown-it-py==3.0.0
      - markupsafe==3.0.2
      - mccabe==0.7.0
      - mdurl==0.1.2
      - mergedeep==1.3.4
      - mkautodoc==0.2.0
      - mkdocs==1.6.1
      - mkdocs-get-deps==0.2.0
      - mkdocs-material==9.6.10
      - mkdocs-material-extensions==1.3.1
      - more-itertools==10.6.0
      - mypy==1.15.0
      - mypy-extensions==1.0.0
      - nh3==0.2.21
      - outcome==1.3.0.post0
      - packaging==24.2
      - paginate==0.5.7
      - pathspec==0.12.1
      - platformdirs==4.3.7
      - pluggy==1.5.0
      - pycodestyle==2.13.0
      - pycparser==2.22
      - pyflakes==3.3.2
      - pygments==2.19.1
      - pymdown-extensions==10.14.3
      - pytest==8.3.5
      - pytest-asyncio==0.26.0
      - pytest-cov==6.0.0
      - pytest-trio==0.8.0
      - python-dateutil==2.9.0.post0
      - pyyaml==6.0.2
      - pyyaml-env-tag==0.1
      - readme-renderer==44.0
      - requests==2.32.3
      - requests-toolbelt==1.0.0
      - rfc3986==1.5.0
      - rich==14.0.0
      - secretstorage==3.3.3
      - seed-isort-config==2.2.0
      - six==1.17.0
      - sniffio==1.3.1
      - sortedcontainers==2.4.0
      - tomli==2.2.1
      - trio==0.29.0
      - trio-typing==0.10.0
      - trustme==1.2.1
      - twine==6.1.0
      - typing-extensions==4.13.0
      - urllib3==2.3.0
      - uvicorn==0.34.0
      - watchdog==6.0.0
      - zipp==3.21.0
prefix: /opt/conda/envs/httpx

tests/test_decoders.py::test_line_decoder_nl tests/test_decoders.py::test_line_decoder_cr tests/test_decoders.py::test_line_decoder_crnl
tests/test_decoders.py::test_deflate tests/test_decoders.py::test_zlib tests/test_decoders.py::test_gzip tests/test_decoders.py::test_brotli tests/test_decoders.py::test_multi tests/test_decoders.py::test_multi_with_identity tests/test_decoders.py::test_streaming tests/test_decoders.py::test_empty_content[deflate] tests/test_decoders.py::test_empty_content[gzip] tests/test_decoders.py::test_empty_content[br] tests/test_decoders.py::test_empty_content[identity] tests/test_decoders.py::test_decoders_empty_cases[BrotliDecoder] tests/test_decoders.py::test_decoders_empty_cases[DeflateDecoder] tests/test_decoders.py::test_decoders_empty_cases[GZipDecoder] tests/test_decoders.py::test_decoders_empty_cases[IdentityDecoder] tests/test_decoders.py::test_decoding_errors[deflate] tests/test_decoders.py::test_decoding_errors[gzip] tests/test_decoders.py::test_decoding_errors[br] tests/test_decoders.py::test_text_decoder[data0-ascii] tests/test_decoders.py::test_text_decoder[data1-utf-8] tests/test_decoders.py::test_text_decoder[data2-shift-jis] tests/test_decoders.py::test_text_decoder[data3-shift-jis] tests/test_decoders.py::test_text_decoder[data4-MacCyrillic] tests/test_decoders.py::test_text_decoder[data5-euc-jp] tests/test_decoders.py::test_text_decoder_known_encoding tests/test_decoders.py::test_text_decoder_empty_cases tests/test_decoders.py::test_invalid_content_encoding_header
requirements.txt httpx/_decoders.py
requirements.txt httpx/_decoders.py