alibaba/spring-ai-alibaba · error · ResponseStatusException
Graph not found:
Error message
Graph not found:
What it means
After the blank check, validateGraphExists compares graphName against graphLoader.listGraphs() and throws a 404 NOT_FOUND ResponseStatusException 'Graph not found: <graphName>' if it is not loaded. All thread endpoints call this before touching threads.
Solutions
- Verify the exact graph name via the graphs listing endpoint / graphLoader.listGraphs().
- Register the graph so it appears in listGraphs() (correct provider/bean configuration in Studio).
- Fix typos and case sensitivity in the client's graphName.
Example fix
// before await fetch(`/graphs/MyGraph/users/u1/threads`); // not registered // after await fetch(`/graphs/my-graph/users/u1/threads`); // name as returned by listGraphs()
Defensive patterns
Strategy: validation
Validate before calling
// before calling thread APIs
const graphs = await (await fetch('/graphs')).json();
if (!graphs.includes(graphName)) throw new Error(`Graph '${graphName}' not loaded in Studio`); Try / catch
try {
await api.get(`/graphs/${graphName}/users/${userId}/threads`);
} catch (e) {
if (e.response?.status === 404 && e.response.data.includes('Graph not found')) {
const graphs = await api.get('/graphs'); // pick a valid name
}
} Prevention
- Discover graph names dynamically from the listing endpoint.
- Register graphs in Studio before using thread APIs.
- Watch for typos and case sensitivity in graph names.
When it happens
Trigger: Calling any thread endpoint (get/list/create/delete) with a graphName that is not registered in the Studio graph loader.
Common situations: Typo or case mismatch in graph name; graph exists in your app code but is not registered with Studio's GraphLoader; graph module not on the Studio classpath.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Graph not found:
- Thread found but belongs to a different graph/user.
- Thread not found: graphName=
- APP_COMPONENT_QUERYCONFIG_ERROR
- APP_COMPONENT_REFER_ERROR
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/1f33a75bab9ffdc5.
Report an issue: GitHub.
Appendix: source
Thrown at spring-ai-alibaba-studio/src/main/java/com/alibaba/cloud/ai/agent/studio/controller/GraphThreadController.java:79
private final ThreadService threadService;
@Autowired
public GraphThreadController(GraphLoader graphLoader, ThreadService threadService) {
this.graphLoader = graphLoader;
this.threadService = threadService;
}
private String toAppName(String graphName) {
return GRAPH_APP_PREFIX + graphName;
}
private void validateGraphExists(String graphName) {
if (graphName == null || graphName.isBlank()) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "graphName cannot be null or empty");
}
if (!graphLoader.listGraphs().contains(graphName)) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Graph not found: " + graphName);
}
}
private Thread findThreadOrThrow(String graphName, String userId, String threadId) {
String appName = toAppName(graphName);
Optional<Thread> optionalThread =
threadService.getThread(appName, userId, threadId, Optional.empty()).block();
if (optionalThread == null || !optionalThread.isPresent()) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND,
String.format("Thread not found: graphName=%s, userId=%s, threadId=%s",
graphName, userId, threadId));
}
Thread thread = optionalThread.get();
if (!Objects.equals(thread.appName(), appName) || !Objects.equals(thread.userId(), userId)) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND,
"Thread found but belongs to a different graph/user.");View on GitHub (pinned to f82da0b50f)