FileArtifactService changes CRLF and CR line endings in text artifacts

Aperta Adatta ai principianti
#7,914 1 commento 0 reazioni 1 assegnatario Vedi su GitHub

I maintainer di solito rispondono entro 4 giorni

@sanketpatil06 ci sta già lavorando.

Dal 2/11/2026.

  • #7915 di @emme1t — aperta
  • #7917 di @TINGyu123644 — chiusa senza merge

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
85/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
python
Ambito
backend

Direzione di ricerca

Inizia da google/adk/artifacts/file_artifact_service.py e segui come viene salvato e caricato il testo; lo script di riproduzione dell’issue mostra i casi di newline da verificare. Esegui lo script, quindi verifica che gli artefatti basati su file restituiscano il testo salvato senza modifiche, inclusi i terminatori di riga CRLF e CR isolato.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

request clarification services

🔴 Required Information

Describe the Bug:

FileArtifactService changes the line endings of text artifacts. A text artifact containing \r\n or a lone \r loads back with \n in their place. The payload is read with Path.read_text, whose universal newline mode rewrites both. It is written with Path.write_text, which translates \n to os.linesep, so on Windows every \n is stored as \r\n.

InMemoryArtifactService and GcsArtifactService return the saved text unchanged, so the same artifact differs only on the file backend. That backend is what adk web and adk run use by default (use_local_storage=True, via create_local_artifact_service). CSV files (RFC 4180 uses CRLF), patches, and Windows-authored text a tool saves therefore load back different from what was saved.

Steps to Reproduce:

  1. pip install google-adk (reproduced on main at 8cd3b12c8)
  2. Run:
import asyncio, tempfile
from google.genai import types
from google.adk.artifacts.file_artifact_service import FileArtifactService
from google.adk.artifacts.in_memory_artifact_service import InMemoryArtifactService

async def main():
  text = "id,name\r\n1,a\r\n2,b\rc\n"
  for svc in (FileArtifactService(root_dir=tempfile.mkdtemp()), InMemoryArtifactService()):
    await svc.save_artifact(app_name="a", user_id="u", session_id="s",
                            filename="t.csv", artifact=types.Part(text=text))
    got = await svc.load_artifact(app_name="a", user_id="u", session_id="s",
                                  filename="t.csv")
    print(type(svc).__name__, repr(got.text), got.text == text)

asyncio.run(main())

Expected Behavior:

Both services return the saved text unchanged.

Observed Behavior:

FileArtifactService 'id,name\n1,a\n2,b\nc\n' False
InMemoryArtifactService 'id,name\r\n1,a\r\n2,b\rc\n' True

Environment Details:

  • ADK Library Version (pip show google-adk): 2.13.0 (main at 8cd3b12c8)
  • Desktop OS: macOS (the read-side rewrite is platform independent; the write-side translation affects Windows)
  • Python Version (python -V): 3.11

Model Information:

  • Are you using LiteLLM: No
  • Which model is being used: N/A (artifact service only)

🟡 Optional Information

Regression:

Not that I know of. The file backend has read and written text payloads with read_text / write_text.

Additional Context:

I would like to contribute a focused fix for this. Would writing artifact.text.encode("utf-8") with write_bytes and decoding read_bytes() on load be an acceptable approach? This keeps the stored payload exactly equal to the saved text. The error handling stays the same (OSError / UnicodeDecodeError are still caught and logged). Metadata JSON reads and writes are unaffected, since JSON escapes CR/LF inside strings.

How often has this issue occurred?:

  • Always (100%)
Lingua principale
Python
Stelle
22.1k
Fork
4.3k
Merge medio
1g 10h
PR unite (30g)
5

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di google/adk-python

Tutte le issue di google/adk-python

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.