﻿id	summary	reporter	owner	description	type	status	priority	milestone	component	version	severity	resolution	keywords	cc	focuses
65781	AI Client: support checks return the prompt builder instead of false when the wrapped builder throws	bejignesh	gziolo	"`WP_AI_Client_Prompt_Builder::__call()` catches an exception from the wrapped SDK builder, stores it as the error state, and then only special cases the generating methods:

{{{#!php
try {
	$callable = $this->get_builder_callable( $name );
	$result   = $callable( ...$arguments );
	...
} catch ( Exception $e ) {
	$this->error = $this->exception_to_wp_error( $e );

	if ( self::is_generating_method( $name ) ) {
		return $this->error;
	}
	return $this;
}
}}}

`is_supported()` and the seven `is_supported_for_*()` methods are not generating methods, so they fall through to the fluent return and hand back the `WP_AI_Client_Prompt_Builder` instance. That object is truthy, so a support check that failed reads as a success:

{{{#!php
if ( wp_ai_client_prompt( 'Write a haiku' )->is_supported() ) {
	// Runs even though the support check could not be completed.
}
}}}

The class handles this correctly everywhere else. The error state guard at the top of `__call()` returns `false` for support checks, and so does the prevented prompt path. Only an exception raised during the support check itself takes the wrong branch.

== Steps to reproduce ==

`ModalityEnum::document()` is a documented factory on the bundled client, but `PromptBuilder::inferCapabilityFromOutputModalities()` has no branch for it and throws a `RuntimeException` in its else. That call sits outside the try block `isSupported()` uses to swallow `InvalidArgumentException`, so it reaches the WordPress wrapper.

{{{#!php
$result = wp_ai_client_prompt( 'Test text' )
	->as_output_modalities( ModalityEnum::document() )
	->is_supported();

var_dump( $result ); // object(WP_AI_Client_Prompt_Builder), expected bool(false)
}}}

Any other throw from the wrapped builder during a support check does the same thing. The document modality is just the shortest path to one.

== Expected ==

Support check methods always return a bool. That is what the `@method` annotations on the class say, and what `test_boolean_methods_return_boolean()` already asserts (""is_supported_for_text_generation should not return the decorator"").

== Patch ==

Return `false` from support check methods in the catch block, matching what they already return when the builder was in an error state beforehand. The error is still stored, so a later generating call still returns the `WP_Error`.

== Note ==

This is not the same as #65505. That ticket is about `catch ( Exception )` missing `Error`, and the patch there widens the catch to `Throwable` while leaving the return logic as is, so this behaviour survives it. The two fixes are independent and touch different lines."	defect (bug)	closed	normal	7.2	AI	7.0	normal	fixed	has-patch has-unit-tests		
