diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java
index 31ca85080b2b0c9acc268ea463576fea2ec0becd..89e3989cea89f50edb964f98b1158b818932f102 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java
@@ -146,7 +146,7 @@ public class TestCasts extends TestBase {
         class Root extends TestRootNode<CastNode> {
 
             protected Root(String name) {
-                super(name, setupAndGetCast(b -> b.firstIntegerWithError(0, Message.INVALID_ARGUMENT, "foo")));
+                super(name, setupAndGetCast(b -> b.arg(0, "foo").asIntegerVector().findFirst()));
             }
 
             @Override
@@ -167,7 +167,7 @@ public class TestCasts extends TestBase {
             private final Object constant;
 
             protected Root(String name, Object constant) {
-                super(name, setupAndGetCast(b -> b.firstIntegerWithError(0, Message.INVALID_ARGUMENT, "foo")));
+                super(name, setupAndGetCast(b -> b.arg(0, "foo").asIntegerVector().findFirst()));
                 this.constant = constant;
             }
 
@@ -205,7 +205,6 @@ public class TestCasts extends TestBase {
     public void testMapDefaultValue() {
         class Root extends TestRootNode<CastNode> {
 
-            @SuppressWarnings("deprecation")
             protected Root(String name) {
                 super(name, setupAndGetCast(b -> b.arg(0).mapNull(constant("X"))));
             }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
index 2e13d1247171c3cf00d3683c7060a68311b4124e..c8774bc64426a4c3b877adc426750ddfaefff495 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
@@ -22,8 +22,6 @@
  */
 package com.oracle.truffle.r.nodes.builtin;
 
-import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
-
 import java.util.Arrays;
 import java.util.function.Consumer;
 
@@ -44,7 +42,6 @@ import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapToCharAt;
 import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapToValue;
 import com.oracle.truffle.r.nodes.builtin.casts.MessageData;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.BoxPrimitiveStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CoercionStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapIfStep;
@@ -58,8 +55,6 @@ import com.oracle.truffle.r.nodes.builtin.casts.fluent.PipelineBuilder;
 import com.oracle.truffle.r.nodes.builtin.casts.fluent.PipelineConfigBuilder;
 import com.oracle.truffle.r.nodes.builtin.casts.fluent.PreinitialPhaseBuilder;
 import com.oracle.truffle.r.nodes.unary.CastNode;
-import com.oracle.truffle.r.nodes.unary.CastToVectorNode;
-import com.oracle.truffle.r.nodes.unary.FindFirstNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -138,105 +133,6 @@ public final class CastBuilder {
         return castsCache;
     }
 
-    // ---------------
-    // Deprecated API:
-    // Converted to the new API preserving original semantics as much as possible
-
-    private PipelineBuilder getBuilderForDeprecated(int index) {
-        PipelineBuilder builder = getBuilder(index, "");
-        builder.getPipelineConfig().allowNull();
-        return builder;
-    }
-
-    public CastBuilder toVector(int index) {
-        PipelineBuilder builder = getBuilderForDeprecated(index);
-        // TODO: asVector with preserveNonVector transforms RNull, this is not compatible with the
-        // semantics of RNull being forwarded by all cast nodes. Because of this we need to map null
-        // for legacy API calls
-        builder.getPipelineConfig().setWasLegacyAsVectorCall();
-        builder.getPipelineConfig().mapNull(new MapToValue<>(RDataFactory.createList()));
-        builder.appendAsVector(false, false, false, false);
-        return this;
-    }
-
-    public CastBuilder toInteger(int index) {
-        PipelineBuilder builder = getBuilderForDeprecated(index);
-        if (builder.getPipelineConfig().wasLegacyAsVectorCall()) {
-            mapNullAndMissing(builder, RDataFactory.createIntVector(0));
-        } else {
-            builder.getPipelineConfig().mapNull(new MapToValue<>(RNull.instance));
-        }
-        builder.appendAsIntegerVector(false, false, false);
-        return this;
-    }
-
-    public CastBuilder toDouble(int index) {
-        PipelineBuilder builder = getBuilderForDeprecated(index);
-        if (builder.getPipelineConfig().wasLegacyAsVectorCall()) {
-            builder.getPipelineConfig().mapNull(new MapToValue<>(RDataFactory.createDoubleVector(0)));
-            // CastDoubleBaseNode does not handle RMissing it seems...
-        } else {
-            allowNullAndMissing(builder);
-        }
-        builder.appendAsDoubleVector(false, false, false);
-        return this;
-    }
-
-    public CastBuilder toLogical(int index) {
-        PipelineBuilder builder = getBuilderForDeprecated(index);
-        if (builder.getPipelineConfig().wasLegacyAsVectorCall()) {
-            mapNullAndMissing(builder, RDataFactory.createLogicalVector(0));
-        } else {
-            allowNullAndMissing(builder);
-        }
-        builder.appendAsLogicalVector(false, false, false);
-        return this;
-    }
-
-    public CastBuilder boxPrimitive(int index) {
-        PipelineBuilder builder = getBuilderForDeprecated(index);
-        allowNullAndMissing(builder);
-        builder.append(new BoxPrimitiveStep<>());
-        return this;
-    }
-
-    public CastBuilder firstIntegerWithError(int index, RError.Message error, String name) {
-        // TODO: check if we can remove FirstIntNode when this is removed...
-        getBuilderForDeprecated(index).appendAsIntegerVector(false, false, false);
-        getBuilderForDeprecated(index).appendFindFirst(null, Integer.class, SHOW_CALLER, error, new Object[]{name});
-        return this;
-    }
-
-    public CastBuilder firstBoolean(int index) {
-        PipelineBuilder builder = getBuilderForDeprecated(index);
-        builder.appendAsLogicalVector(false, false, false);
-        builder.appendFindFirst(null, Byte.class, SHOW_CALLER, RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL, new Object[0]);
-        builder.appendMap(MapByteToBoolean.INSTANCE);
-        return this;
-    }
-
-    public CastBuilder firstBoolean(int index, String invalidValueName) {
-        if (invalidValueName == null) {
-            return firstBoolean(index);
-        }
-        PipelineBuilder builder = getBuilderForDeprecated(index);
-        builder.appendAsLogicalVector(false, false, false);
-        builder.appendFindFirst(null, Byte.class, SHOW_CALLER, RError.Message.INVALID_VALUE, new Object[]{invalidValueName});
-        builder.appendMap(MapByteToBoolean.INSTANCE);
-        return this;
-    }
-
-    private void allowNullAndMissing(PipelineBuilder builder) {
-        builder.getPipelineConfig().mapNull(new MapToValue<>(RNull.instance));
-        builder.getPipelineConfig().mapMissing(new MapToValue<>(RMissing.instance));
-    }
-
-    private void mapNullAndMissing(PipelineBuilder builder, Object value) {
-        builder.getPipelineConfig().mapNull(new MapToValue<>(value));
-        builder.getPipelineConfig().mapMissing(new MapToValue<>(value));
-    }
-
-    // end of deprecated API:
     // ---------------------
     // The cast-pipelines API starts here
 
@@ -884,6 +780,5 @@ public final class CastBuilder {
         public static <T> MapToValue<T, RList> emptyList() {
             return new MapToValue<>(RDataFactory.createList());
         }
-
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java
index 288dde89c583cba87639b1a3f032adf5c6e79a3c..a13c29fc1cad2114fe791f136ffc9d55f9f91550 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java
@@ -22,9 +22,6 @@
  */
 package com.oracle.truffle.r.nodes.builtin.casts;
 
-import java.util.function.Supplier;
-
-import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
@@ -71,8 +68,6 @@ public abstract class PipelineStep<T, R> {
 
         T visit(BoxPrimitiveStep<?> step);
 
-        T visit(CustomNodeStep<?> step);
-
         T visit(AttributableCoercionStep<?> step);
     }
 
@@ -339,26 +334,4 @@ public abstract class PipelineStep<T, R> {
             return visitor.visit(this);
         }
     }
-
-    /**
-     * Allows to insert arbitrary node into the cast pipeline. Should be avoided as much as
-     * possible, because it hinders inference of any semantics from the pipeline intermediate
-     * representation. This step is here for legacy reasons and will be removed in the future.
-     */
-    public static final class CustomNodeStep<T> extends PipelineStep<T, Object> {
-        private final Supplier<CastNode> factory;
-
-        public CustomNodeStep(Supplier<CastNode> factory) {
-            this.factory = factory;
-        }
-
-        public Supplier<CastNode> getFactory() {
-            return factory;
-        }
-
-        @Override
-        public <D> D accept(PipelineStepVisitor<D> visitor) {
-            return visitor.visit(this);
-        }
-    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
index 64ecd64daccc7eeefb5f5251730ac5c076bf47f0..23de8e109efcf466c71ee0624cee29cd15c505a8 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
@@ -50,7 +50,6 @@ import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapperVisitor;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.AttributableCoercionStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.BoxPrimitiveStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CoercionStep;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CustomNodeStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultErrorStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultWarningStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep;
@@ -242,12 +241,6 @@ public final class PipelineToCastNode {
             return inner.visit(step);
         }
 
-        @Override
-        public CastNode visit(CustomNodeStep<?> step) {
-            cannotBeOptimizedBeforeFindFirst();
-            return inner.visit(step);
-        }
-
         @Override
         public CastNode visit(AttributableCoercionStep<?> step) {
             cannotBeOptimizedBeforeFindFirst();
@@ -353,11 +346,6 @@ public final class PipelineToCastNode {
             return BoxPrimitiveNode.create();
         }
 
-        @Override
-        public CastNode visit(CustomNodeStep<?> step) {
-            return step.getFactory().get();
-        }
-
         @Override
         public CastNode visit(FindFirstStep<?, ?> step) {
             boxPrimitives = false;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/ArgCastBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/ArgCastBuilder.java
index bb0a694e8244a7217b01b5095c4bad8ab3e778b0..3811fe65a1a8c14bd7f061d0f9b35a05eded4909 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/ArgCastBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/ArgCastBuilder.java
@@ -23,11 +23,8 @@
 package com.oracle.truffle.r.nodes.builtin.casts.fluent;
 
 import java.util.function.Function;
-import java.util.function.Supplier;
 
 import com.oracle.truffle.r.nodes.builtin.casts.Filter;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CustomNodeStep;
-import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
@@ -78,14 +75,6 @@ public class ArgCastBuilder<T, THIS> {
         return (THIS) this;
     }
 
-    /**
-     * Custom nodes in cast pipeline block optimisations and analysis, use them sparsely.
-     */
-    public THIS customNode(Supplier<CastNode> castNodeFactory) {
-        pipelineBuilder().append(new CustomNodeStep<>(castNodeFactory));
-        return (THIS) this;
-    }
-
     public <R, THAT extends ArgCastBuilder<R, THAT>> THAT alias(Function<THIS, THAT> aliaser) {
         return aliaser.apply((THIS) this);
     }