title: Type Error: The return type must be a string, dict, tuple, Response instance, or WSGI callable, but it was a list
body: <p>I'm making a Flask App that would take an image input ,process it and save the results in a JSON file,but after processing the image it gives me a Type Error mentioned in the title.To add more,it prints only one line and then stops;
  Below is my Flask API that I'm using;</p>
  
  <pre><code>    @app.route('/upload',methods=['GET','POST'])
  def upload_analyze():
  
      if request.method == 'POST':
          # check if a file was passed into the POST request
          if 'file' not in request.files:
              flash('No file was uploaded.')
              return redirect(request.url)     
          f = request.files['file']
          filename = secure_filename(f.filename)
          f.save(filename)
          image = cv2.imread(filename)
          #f.save(secure_filename(f.filename))    
  
          #return 'file uploaded successfully'
          # image_file = request.files['image']
  
  
          clt = KMeans(n_clusters = 3)
          dataset = pd.read_csv('bb22.csv') 
          X = dataset.iloc[:, 1: 8].values
          sc = StandardScaler()
          global orig , r
              # load the image, convert it to grayscale, and blur it slightly
          #images = np.array(Image.open(image_file))
          gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
          gray = cv2.GaussianBlur(gray, (7, 7), 0)
  
              # perform edge detection, then perform a dilation + erosion to
              # close gaps in between object edges
          edged = cv2.Canny(gray, 50, 100)
          edged = cv2.dilate(edged, None, iterations=1)
          edged = cv2.erode(edged, None, iterations=1)
  
              # find contours in the edge map
          cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
          cnts = cnts[0] if imutils.is_cv2() else cnts[1]
  
              # sort the contours from left-to-right and initialize the
              # 'pixels per metric' calibration variable
          (cnts, _) = contours.sort_contours(cnts)
          pixelsPerMetric = None
  
          object_num = 0
          r=object_num
          objects = []
  
          idx=0
  
          orig = image.copy()
          counter = 0
          leng = [0] * 400
          width = [0] *400
              # loop over the contours individually
          for c in cnts:
  # if the contour is not sufficiently large, ignore it
              if cv2.contourArea(c) &lt; 50:
                  continue
                  # compute the rotated bounding box of the contour
              box = cv2.minAreaRect(c)
              box = cv2.cv.BoxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box)
              box = np.array(box, dtype="int")
                  # order the points in the contour such that they appear
                  # in top-left, top-right, bottom-right, and bottom-left
                   # order, then draw the outline of the rotated bounding box
              box = perspective.order_points(box)
              cv2.drawContours(orig, [box.astype("int")], -1, (0, 255, 0), 2)
              box.astype
                   # unpack the ordered bounding box, then compute the midpoint
                   # between the top-left and top-right coordinates, followed by
                   # the midpoint between bottom-left and bottom-right coordinates
              (tl, tr, br, bl) = box
              (tltrX, tltrY) = midpoint(tl, tr)
              (blbrX, blbrY) = midpoint(bl, br)
                   # compute the midpoint between the top-left and top-right points,
                   # followed by the midpoint between the top-righ and bottom-right
              (tlblX, tlblY) = midpoint(tl, bl)
              (trbrX, trbrY) = midpoint(tr, br)
  
                   # compute the Euclidean distance between the midpoints
              dA = dist.euclidean((tltrX, tltrY), (blbrX, blbrY))
              dB = dist.euclidean((tlblX, tlblY), (trbrX, trbrY))
  
                   # if the pixels per metric has not been initialized, then
                   # compute it as the ratio of pixels to supplied metric (in this case, inches)
              if pixelsPerMetric is None:
                  pixelsPerMetric = dB / 22.599 #previously its /22.50
  
                   # compute the size of the object
              area = round(cv2.contourArea(c) / (pixelsPerMetric**2), 3)
              perimeter = round(cv2.arcLength(c, True)/ pixelsPerMetric, 3)
              hull = cv2.convexHull(c)
              hull_area = round(cv2.contourArea(hull) / (pixelsPerMetric**2), 3)
              (x,y),(ma,MA),angle = cv2.fitEllipse(c)
              eccentricity = round(np.sqrt(1-(ma/MA)**2),3)
              C = round(4*np.pi*area/perimeter**2, 3)
              dimA = round(dA / pixelsPerMetric, 3)
              dimB = round(dB / pixelsPerMetric, 3)
              if (dimA &gt;= dimB):
                  temp=dimA
                  dimA=dimB
                  dimB=temp
  
              leng[counter] = str(dimB)
              width[counter] = str(dimA)
              counter = counter +1
  
              x,y,w,h = cv2.boundingRect(c)
              idx+=1
              mask = np.zeros(image.shape[:2],np.uint8)
              cv2.drawContours(mask, [c],-1, 255, -1)
              dst = cv2.bitwise_and(image, image, mask=mask)
              new_img=dst[y-20:y+h+20,x-20:x+w+20]
  
                  # pre-process the image for classification
              if len(new_img) == 0:
                  WB = 0
                  continue
  
              object_num = object_num+1
              image1 = cv2.cvtColor(new_img, cv2.COLOR_BGR2RGB)
              image1 = new_img.reshape((image1.shape[0] * new_img.shape[1], 3))
  
                  #classify color
              clt.fit(image1)
              count = 0
              global dominant_color
              dominant_color = [0,0,0]
  
              for (color) in (clt.cluster_centers_):
                  a = [color.astype("uint8").tolist()[0], color.astype("uint8").tolist()[1],
                   color.astype("uint8").tolist()[2]]
                  count = count+1
                  if(count == 2) and (a != [0, 0, 0]):
                      dominant_color = a
  
                  #prepare image for broken classification
              new_img = cv2.resize(new_img, (64, 64))
              new_img = new_img.astype("float") / 255.0
              new_img = img_to_array(new_img)
              new_img = np.expand_dims(new_img, axis=0)
  
                  # classify the input image
              with graph.as_default():
  
                  (yes, no) = model.predict(new_img)[0]
  
                      # build the label
                  if (yes &gt; no):
                      WB = 0
                      y_new = "Broken"
                  else:
  
                      if object_num == 1:
                          print("true")
                          continue
                      WB = 1
                      X_new = array([[dimA, dimB, area, perimeter, hull_area, eccentricity, C]])
                      X=sc.fit_transform(X)
                      X_new = sc.transform(X_new)
                      y_new = type_model.predict(X_new)
                      print("X=%s, Predicted=%s" % (X_new[0], y_new))
  
                      obj_num=object_num-1 # because one item on the left most side we have for the pixel constant value
  
  
                  content = {
                      "Object_number": obj_num,
                      "Width": dimA,
                      "Length": dimB,
                      #"Area": area,
                      #"Perimeter": perimeter,
                      #"hull_area": hull_area,
                      #"eccentricity": eccentricity,
                      #"compactness": C,
                      "WB": WB # Whole or Broken
                      #"Type": str(y_new[0]),
                      #"color_rgb": dominant_color,
                      #"color_hex": rgb2hex(dominant_color[2], dominant_color[1], dominant_color[0])
                      }
  
                  objects.append(content)
  
              return(objects)
  
          objects=analyze()
          with open('test6.json', 'w') as fout:
              json.dump(objects , fout)
          print(objects)
          print(type(objects))
          return 'ok'
  </code></pre>
  
  <p>Also in console only this 1 line gets printed:</p>
  
  <pre><code>X=[ 0.38739663 -0.25583995  0.22674784 -0.2933872   0.19980647 -0.03758974
    0.4759277 ], Predicted=[4]
  </code></pre>
  
  <p>I'm returning this message to make sure that the JSON file is created but it doesn't gets created..I can't figure out what is wrong with the return type ..kindly help.</p>