diff --git a/react/actions/index.js b/react/actions/index.js
index 3c730282..1ba9bfff 100644
--- a/react/actions/index.js
+++ b/react/actions/index.js
@@ -6,6 +6,7 @@ export const CLAIM_UPDATE = 'CLAIM_UPDATE';
 export const CHANNEL_UPDATE = 'CHANNEL_UPDATE';
 export const SET_PUBLISH_IN_CHANNEL = 'SET_PUBLISH_IN_CHANNEL';
 export const PUBLISH_STATUS_UPDATE = 'PUBLISH_STATUS_UPDATE';
+export const ERROR_UPDATE = 'ERROR_UPDATE';
 
 // export action creators
 export function selectFile (file) {
@@ -59,3 +60,11 @@ export function updatePublishStatus (status, message) {
     message,
   };
 };
+
+export function updateError (name, value) {
+  return {
+    type: ERROR_UPDATE,
+    name,
+    value,
+  };
+};
diff --git a/react/containers/ChannelCreateForm.jsx b/react/containers/ChannelCreateForm.jsx
index b742e559..f8a0923f 100644
--- a/react/containers/ChannelCreateForm.jsx
+++ b/react/containers/ChannelCreateForm.jsx
@@ -20,6 +20,7 @@ class ChannelCreateForm extends React.Component {
     this.updateIsChannelAvailable = this.updateIsChannelAvailable.bind(this);
     this.checkIsChannelAvailable = this.checkIsChannelAvailable.bind(this);
     this.checkIsPasswordProvided = this.checkIsPasswordProvided.bind(this);
+    this.makePublishChannelRequest = this.makePublishChannelRequest.bind(this);
     this.createChannel = this.createChannel.bind(this);
   }
   cleanseChannelInput (input) {
@@ -88,12 +89,12 @@ class ChannelCreateForm extends React.Component {
       resolve();
     });
   }
-  makeCreateChannelRequest (channel, password) {
+  makePublishChannelRequest (channel, password) {
     const params = `username=${channel}&password=${password}`;
     return new Promise((resolve, reject) => {
       makePostRequest('/signup', params)
         .then(result => {
-          resolve(result);
+          return resolve(result);
         })
         .catch(error => {
           console.log('create channel request failed:', error);
@@ -110,7 +111,7 @@ class ChannelCreateForm extends React.Component {
       })
       .then(() => {
         that.setState({status: 'We are publishing your new channel.  Sit tight...'});
-        return that.makeCreateChannelRequest();
+        return that.makePublishChannelRequest(that.state.channel, that.state.password);
       })
       .then(result => {
         that.setState({status: null});
diff --git a/react/containers/Dropzone.jsx b/react/containers/Dropzone.jsx
index 16dbeb53..5f477625 100644
--- a/react/containers/Dropzone.jsx
+++ b/react/containers/Dropzone.jsx
@@ -1,16 +1,14 @@
 import React from 'react';
 // import PropTypes from 'prop-types';
-import { selectFile } from '../actions/index';
+import { selectFile, updateError } from '../actions';
 import { connect } from 'react-redux';
 import Preview from '../components/Preview.jsx';
-
 import { validateFile } from '../utils/file.js';
 
 class Dropzone extends React.Component {
   constructor (props) {
     super(props);
     this.state = {
-      fileError : null,
       dragOver  : false,
       mouseOver : false,
       dimPreview: false,
@@ -79,10 +77,10 @@ class Dropzone extends React.Component {
       try {
         validateFile(file); // validate the file's name, type, and size
       } catch (error) {
-        return this.setState({fileError: error.message});
+        return this.props.onFileError(error.message);
       }
       // stage it so it will be ready when the publish button is clicked
-      this.setState({fileError: null});
+      this.props.onFileError(null);
       this.props.onFileSelect(file);
     }
   }
@@ -110,7 +108,7 @@ class Dropzone extends React.Component {
               )}
               { this.state.mouseOver ? (
                 <div id="dropzone-instructions">
-                  <p className="info-message-placeholder info-message--failure" id="input-error-file-selection">{this.state.fileError}</p>
+                  <p className="info-message-placeholder info-message--failure" id="input-error-file-selection">{this.props.fileError}</p>
                   <p>Drag & drop image or video here to publish</p>
                   <p className="fine-print">OR</p>
                   <p className="blue--underlined">CHOOSE FILE</p>
@@ -128,7 +126,7 @@ class Dropzone extends React.Component {
                 </div>
               ) : (
                 <div id="dropzone-instructions">
-                  <p className="info-message-placeholder info-message--failure" id="input-error-file-selection">{this.state.fileError}</p>
+                  <p className="info-message-placeholder info-message--failure" id="input-error-file-selection">{this.props.fileError}</p>
                   <p>Drag & drop image or video here to publish</p>
                   <p className="fine-print">OR</p>
                   <p className="blue--underlined">CHOOSE FILE</p>
@@ -146,6 +144,7 @@ const mapStateToProps = state => {
   return {
     file     : state.file,
     thumbnail: state.metadata.thumbnail,
+    fileError: state.error.file,
   };
 };
 
@@ -154,6 +153,9 @@ const mapDispatchToProps = dispatch => {
     onFileSelect: (file) => {
       dispatch(selectFile(file));
     },
+    onFileError: (value) => {
+      dispatch(updateError('file', value));
+    },
   };
 }
 
diff --git a/react/containers/PublishForm.jsx b/react/containers/PublishForm.jsx
index 89cea2ec..6926484c 100644
--- a/react/containers/PublishForm.jsx
+++ b/react/containers/PublishForm.jsx
@@ -8,7 +8,7 @@ import PublishMetadataInputs from './PublishMetadataInputs.jsx';
 import AnonymousOrChannelSelect from './AnonymousOrChannelSelect.jsx';
 import { connect } from 'react-redux';
 import { getCookie } from '../utils/cookies.js';
-import { selectFile, clearFile, updateLoggedInChannel, updatePublishStatus } from '../actions';
+import {selectFile, clearFile, updateLoggedInChannel, updatePublishStatus, updateError} from '../actions';
 
 const LOAD_START = 'LOAD_START';
 const LOADING = 'LOADING';
@@ -19,10 +19,6 @@ const FAILED = 'FAILED';
 class PublishForm extends React.Component {
   constructor (props) {
     super(props);
-    // set defaults
-    this.state = {
-      publishRequestError: null,
-    };
     this.validatePublishRequest = this.validatePublishRequest.bind(this);
     this.makePublishRequest = this.makePublishRequest.bind(this);
     this.publish = this.publish.bind(this);
@@ -46,11 +42,14 @@ class PublishForm extends React.Component {
       if (!this.props.claim) {
         return reject(new Error('Please enter a URL'));
       }
+      if (this.props.urlError) {
+        return reject(new Error('Fix the url'));
+      }
       // if publishInChannel is true, is a channel logged in (or selected)
       if (this.props.publishInChannel && !this.props.loggedInChannel.name) {
         return reject(new Error('Select "Anonymous" or log in to a channel'));
       }
-      // tbd: is the claim available?
+      // is the claim available?
       resolve();
     });
   }
@@ -131,7 +130,7 @@ class PublishForm extends React.Component {
         that.props.onPublishStatusChange('publish request made');
       })
       .catch((error) => {
-        that.setState({publishRequestError: error.message});
+        that.props.onPublishRequestError(error.message);
       });
   }
   render () {
@@ -175,7 +174,7 @@ class PublishForm extends React.Component {
             </div>
 
             <div className="row row--padded row--wide align-content-center">
-              <p className="info-message-placeholder info-message--failure">{this.state.publishRequestError}</p>
+              <p className="info-message-placeholder info-message--failure">{this.props.publishRequestError}</p>
               <button id="publish-submit" className="button--primary button--large" onClick={this.publish}>Publish</button>
             </div>
 
@@ -196,15 +195,18 @@ class PublishForm extends React.Component {
 
 const mapStateToProps = state => {
   return {
-    file            : state.file,
-    claim           : state.claim,
-    title           : state.metadata.title,
-    thumbnail       : state.metadata.thumbnail,
-    description     : state.metadata.description,
-    license         : state.metadata.license,
-    nsfw            : state.metadata.nsfw,
-    loggedInChannel : state.loggedInChannel,
-    publishInChannel: state.publishInChannel,
+    file               : state.file,
+    claim              : state.claim,
+    title              : state.metadata.title,
+    thumbnail          : state.metadata.thumbnail,
+    description        : state.metadata.description,
+    license            : state.metadata.license,
+    nsfw               : state.metadata.nsfw,
+    loggedInChannel    : state.loggedInChannel,
+    publishInChannel   : state.publishInChannel,
+    fileError          : state.error.file,
+    urlError           : state.error.url,
+    publishRequestError: state.error.publishRequest,
   };
 };
 
@@ -222,6 +224,9 @@ const mapDispatchToProps = dispatch => {
     onPublishStatusChange: (status, message) => {
       dispatch(updatePublishStatus(status, message));
     },
+    onPublishRequestError: (value) => {
+      dispatch(updateError('publishRequest', value));
+    },
   };
 };
 
diff --git a/react/containers/PublishUrlInput.jsx b/react/containers/PublishUrlInput.jsx
index dbf1f1fc..0a42e2ae 100644
--- a/react/containers/PublishUrlInput.jsx
+++ b/react/containers/PublishUrlInput.jsx
@@ -3,12 +3,12 @@ import { updateClaim } from '../actions/index';
 import { connect } from 'react-redux';
 import { makeGetRequest } from '../utils/xhr.js';
 import UrlMiddle from '../components/PublishUrlMiddle.jsx';
+import {updateError} from '../actions';
 
 class UrlChooser extends React.Component {
   constructor (props) {
     super(props);
     this.state = {
-      error    : null,
       host     : 'spee.ch',
       urlMiddle: null,
     };
@@ -27,7 +27,7 @@ class UrlChooser extends React.Component {
     if (newClaim) {
       this.checkClaimIsAvailable(newClaim);
     } else {
-      this.setState({error: 'Please enter a URL'});
+      this.props.onUrlError('Please enter a URL');
     }
   }
   handleInput (event) {
@@ -53,19 +53,19 @@ class UrlChooser extends React.Component {
     makeGetRequest(`/api/claim-is-available/${claim}`)
       .then(response => {
         if (response) {
-          that.setState({'error': null});
+          this.props.onUrlError(null);
         } else {
-          that.setState({'error': 'That url has already been claimed'});
+          this.props.onUrlError('That url has already been claimed');
         }
       })
       .catch((error) => {
-        that.setState({'error': error.message});
+        this.props.onUrlError(error.message);
       });
   }
   render () {
     return (
       <div>
-        <p id="input-error-claim-name" className="info-message-placeholder info-message--failure">{this.state.error}</p>
+        <p id="input-error-claim-name" className="info-message-placeholder info-message--failure">{this.props.urlError}</p>
         <div className="column column--3 column--sml-10">
           <label className="label">URL:</label>
         </div><div className="column column--7 column--sml-10 input-text--primary span--relative">
@@ -75,7 +75,7 @@ class UrlChooser extends React.Component {
           <UrlMiddle publishInChannel={this.props.publishInChannel} loggedInChannelName={this.props.loggedInChannelName} loggedInChannelShortId={this.props.loggedInChannelShortId}/>
 
           <input type="text" id="claim-name-input" className="input-text" name='claim' placeholder="your-url-here" onChange={this.handleInput} value={this.props.claim}/>
-          { (this.props.claim && !this.state.error) && <span id="input-success-claim-name" className="info-message--success span--absolute">{'\u2713'}</span> }
+          { (this.props.claim && !this.props.urlError) && <span id="input-success-claim-name" className="info-message--success span--absolute">{'\u2713'}</span> }
         </div>
       </div>
     );
@@ -89,6 +89,7 @@ const mapStateToProps = state => {
     loggedInChannelShortId: state.loggedInChannel.shortId,
     publishInChannel      : state.publishInChannel,
     claim                 : state.claim,
+    urlError              : state.error.url,
   };
 };
 
@@ -97,6 +98,9 @@ const mapDispatchToProps = dispatch => {
     onClaimChange: (value) => {
       dispatch(updateClaim(value));
     },
+    onUrlError: (value) => {
+      dispatch(updateError('url', value));
+    },
   };
 }
 
diff --git a/react/reducers/index.js b/react/reducers/index.js
index f67a4e2d..72b4e341 100644
--- a/react/reducers/index.js
+++ b/react/reducers/index.js
@@ -1,5 +1,5 @@
 import {
-  CHANNEL_UPDATE, CLAIM_UPDATE, FILE_CLEAR, FILE_SELECTED, METADATA_UPDATE, PUBLISH_STATUS_UPDATE,
+  CHANNEL_UPDATE, CLAIM_UPDATE, ERROR_UPDATE, FILE_CLEAR, FILE_SELECTED, METADATA_UPDATE, PUBLISH_STATUS_UPDATE,
   SET_PUBLISH_IN_CHANNEL,
 } from '../actions';
 
@@ -14,7 +14,11 @@ const initialState = {
     status : null,
     message: null,
   },
-  error   : null,
+  error: {
+    file          : null,
+    url           : null,
+    publishRequest: null,
+  },
   file    : null,
   claim   : '',
   metadata: {
@@ -62,11 +66,17 @@ export default function (state = initialState, action) {
       });
     case PUBLISH_STATUS_UPDATE:
       return Object.assign({}, state, {
-        status: Object.assign({}, state.metadata, {
+        status: Object.assign({}, state.status, {
           status : action.status,
           message: action.message,
         }),
       });
+    case ERROR_UPDATE:
+      return Object.assign({}, state, {
+        error: Object.assign({}, state.error, {
+          [action.name]: action.value,
+        }),
+      });
     default:
       return state;
   }