Actually... on second thought you can't return null from add since tapestry needs to render the empty record.
Try this instead: eg: <t:ajaxformloop t:id="foos" source="foos" value="foo" encoder="nullNewEncoder">...</t:ajaxformloop> public class NullNewValueEncoder<T> implements ValueEncoder<T> { private static final String CLIENT_NULL = "XXX"; private ValueEncoder<T> encoder; private Class<T> type; public NullNewValueEncoder<T>(ValueEncoderSource source, Class<T> type) { this.encoder = source.getValueEncoder(type); this.type = type; } public String toClient(T value) { String client = encoder.toClient(value); if (client == null) { // eg hibernate entity id was null return CLIENT_NULL; } } public T toValue(String client) { if (CLIENT_NULL.equals(client)) { // this object will be used in the POST request (requires no-args constructor) return type.newInstance(); } return encoder.toValue(client); } } public class MyPage { @Property private List<Foo> foos; @Property private Foo foo; @Inject private ValueEncoderSource source; public ValueEncoder<Foo> getNullNewEncoder() { return new NullNewValueEncoder(source, Foo.class); } public Foo onAddRowFromFoos() { // this object will be used to render the empty row then discarded return new Foo(); } }