Troubleshooting
Quick fixes for common artifact errors in ADK-TS — missing service, null returns, GCS auth, and base64 issues.
Most artifact errors fall into one of three categories: the service isn't wired up, a file doesn't exist where you expect it, or a GCS credential or permission is misconfigured. The sections below cover each with a diagnosis and fix.
For general ADK-TS issues (runner errors, session problems, model errors), see the framework troubleshooting guide.
Common issues
| Issue | Cause | Fix |
|---|---|---|
"Artifact service is not initialized" | No service passed to Runner | Call .withArtifactService() on AgentBuilder, or pass artifactService to Runner directly |
loadArtifact returns undefined | Artifact or version doesn't exist | Check the filename, scope (user: prefix for user-scoped), and version number |
Auto-save (saveInputBlobsAsArtifacts) not working | Service not wired, or wrong part type | Confirm artifactService is configured. Message parts must use inlineData, not text |
GCS 403 Forbidden | Missing IAM permissions | Service account needs roles/storage.objectAdmin on the bucket. Verify ADC or keyFilename |
GCS 412 Precondition Failed on save | Concurrent write conflict | Retry after a short delay — the GCS service uses ifGenerationMatch: 0 which fails on race conditions |
| Wrong data after load | Loaded an old version | Omit the version argument to always get the latest, or pass the exact version number |
artifact.inlineData is undefined | Artifact was saved as { text } | Check artifact.text instead of artifact.inlineData.data |
deleteArtifact not found on context | By design — not exposed on contexts | Call it directly on the service instance, not through CallbackContext or ToolContext |
Wiring check
If you're seeing "Artifact service is not initialized", verify that the service is actually passed to the runner. The recommended way is through AgentBuilder:
import { AgentBuilder, InMemoryArtifactService } from "@iqai/adk";
const { runner } = await AgentBuilder.create("my_agent")
.withModel("gemini-2.5-flash")
.withArtifactService(new InMemoryArtifactService()) // ← required
.build();If you're constructing Runner directly, pass it in the options object:
import {
Runner,
LlmAgent,
InMemorySessionService,
InMemoryArtifactService,
} from "@iqai/adk";
const runner = new Runner({
appName: "my_app",
agent: new LlmAgent({ name: "my_agent", model: "gemini-2.5-flash" }),
sessionService: new InMemorySessionService(),
artifactService: new InMemoryArtifactService(), // ← required
});Safe load pattern
loadArtifact returns undefined if the artifact doesn't exist or the version is out of range. Always guard the return value before accessing its fields, and check both text and inlineData since either can be present depending on how the artifact was saved:
const artifact = await ctx.loadArtifact("maybe_exists.txt");
if (!artifact) {
return { error: "not found" };
}
if (artifact.text) {
console.log(artifact.text);
} else if (artifact.inlineData) {
const content = Buffer.from(artifact.inlineData.data, "base64").toString(
"utf-8",
);
console.log(content);
}GCS auth check
If you're getting 403 Forbidden from GCS, run these commands to verify your credentials are active and the service account has the right permissions on the bucket:
# Confirm active credentials can generate an access token
gcloud auth application-default print-access-token
# Inspect the bucket's IAM policy — look for your service account with roles/storage.objectAdmin
gsutil iam get gs://my-artifacts-bucketIf your service account is missing from the output, grant access:
gsutil iam ch serviceAccount:svc@project.iam.gserviceaccount.com:roles/storage.objectAdmin gs://my-artifacts-bucket